<PackageReference Include="Relativity.Server.Transfer.SDK" Version="24000.0.1" />

FileRemover

using Polly; using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Text; using System.Text.RegularExpressions; namespace Relativity.Transfer { internal class FileRemover : IFileRemover { private const string _UNAVAILABLE_FILE_MESSAGE_PATTERN = "The process cannot access the file '(.+)' because it is being used by another process"; private readonly ITransferLog log; private readonly IFileSystemService fileSystemService; private readonly Policy policy; public FileRemover(ITransferLog log, IFileSystemService fileSystemService = null, Policy policy = null) { if (log == null) throw new ArgumentNullException("log"); this.log = log; this.fileSystemService = (fileSystemService ?? new FileSystemService()); this.policy = (policy ?? CreateDeleteFilePolicy(LogPolicyException)); } public void RemoveFile(string path) { policy.Execute((Action)delegate { fileSystemService.DeleteFile(path); }); } private Policy CreateDeleteFilePolicy(Action<Exception, TimeSpan, int, Context> onRetry) { return RetrySyntax.WaitAndRetry(Policy.Handle<IOException>(), 3, (Func<int, TimeSpan>)((int retryNumber) => TimeSpan.FromSeconds(Math.Pow(3, (double)retryNumber))), onRetry); } private void LogPolicyException(Exception exception, TimeSpan span, int retry, Context context) { if (IsCannotAccessFileException(exception)) { List<object> list = new List<object>(); string text = UnavailableFilePath(exception.Message); StringBuilder stringBuilder = new StringBuilder("Error deleting file '{Path}', retry #{Retry}."); list.Add(text); list.Add(retry); IList<Process> processesUsingFiles = InUseDetection.GetProcessesUsingFiles(new string[1] { text }); stringBuilder.Append(" There are {ProcessCount} presses using it."); list.Add(processesUsingFiles.Count); for (int i = 0; i < processesUsingFiles.Count; i++) { Process process = processesUsingFiles[i]; stringBuilder.Append(" Process #{ProcessNumber}:"); list.Add(i + 1); stringBuilder.Append(" Name: {ProcessName}"); list.Add(process.ProcessName); stringBuilder.Append(", Id: {ProcessId}"); list.Add(process.Id); stringBuilder.Append(", Start time (UTC): {ProcessStartTime}"); list.Add(process.StartTime.ToUniversalTime()); stringBuilder.Append(", User name: {ProcessUser}"); list.Add(process.StartInfo.UserName); stringBuilder.Append(", Process file: {ProcessFile}"); try { list.Add(process.MainModule?.FileName); } catch (Win32Exception) { list.Add("INFORMATION UNAVAILABLE"); } stringBuilder.Append("."); } log.LogError(stringBuilder.ToString(), list); } } private static string UnavailableFilePath(string exceptionMessage) { return Regex.Match(exceptionMessage, "The process cannot access the file '(.+)' because it is being used by another process").Groups[1].Value; } private static bool IsCannotAccessFileException(Exception exception) { if (exception != null && exception.Message != null) return Regex.IsMatch(exception.Message, "The process cannot access the file '(.+)' because it is being used by another process"); return false; } } }