mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-22 09:14:25 +08:00
99 lines
2.7 KiB
C#
99 lines
2.7 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Threading;
|
|
|
|
namespace LanMountainDesktop.Services;
|
|
|
|
internal static class FileOperationRetryHelper
|
|
{
|
|
private static readonly TimeSpan[] RetryDelays =
|
|
[
|
|
TimeSpan.FromMilliseconds(120),
|
|
TimeSpan.FromMilliseconds(250),
|
|
TimeSpan.FromMilliseconds(500)
|
|
];
|
|
|
|
public static void CopyWithRetry(string sourceFilePath, string destinationFilePath, bool overwrite, string category)
|
|
{
|
|
Retry(
|
|
() => File.Copy(sourceFilePath, destinationFilePath, overwrite),
|
|
category,
|
|
$"Copy '{sourceFilePath}' -> '{destinationFilePath}'");
|
|
}
|
|
|
|
public static void MoveWithOverwriteRetry(string sourceFilePath, string destinationFilePath, string category)
|
|
{
|
|
Retry(
|
|
() => File.Move(sourceFilePath, destinationFilePath, overwrite: true),
|
|
category,
|
|
$"Move '{sourceFilePath}' -> '{destinationFilePath}'");
|
|
}
|
|
|
|
public static void DeleteFileWithRetry(string filePath, string category)
|
|
{
|
|
Retry(
|
|
() =>
|
|
{
|
|
if (File.Exists(filePath))
|
|
{
|
|
File.Delete(filePath);
|
|
}
|
|
},
|
|
category,
|
|
$"Delete file '{filePath}'");
|
|
}
|
|
|
|
public static void DeleteDirectoryWithRetry(string directoryPath, bool recursive, string category)
|
|
{
|
|
Retry(
|
|
() =>
|
|
{
|
|
if (Directory.Exists(directoryPath))
|
|
{
|
|
Directory.Delete(directoryPath, recursive);
|
|
}
|
|
},
|
|
category,
|
|
$"Delete directory '{directoryPath}'");
|
|
}
|
|
|
|
private static void Retry(Action action, string category, string operationDescription)
|
|
{
|
|
Exception? lastException = null;
|
|
|
|
for (var attempt = 0; attempt <= RetryDelays.Length; attempt++)
|
|
{
|
|
try
|
|
{
|
|
action();
|
|
return;
|
|
}
|
|
catch (Exception ex) when (IsRetriable(ex))
|
|
{
|
|
lastException = ex;
|
|
if (attempt >= RetryDelays.Length)
|
|
{
|
|
break;
|
|
}
|
|
|
|
var delay = RetryDelays[attempt];
|
|
AppLogger.Warn(
|
|
category,
|
|
$"{operationDescription} failed on attempt {attempt + 1}. Retrying after {delay.TotalMilliseconds:0} ms.",
|
|
ex);
|
|
Thread.Sleep(delay);
|
|
}
|
|
}
|
|
|
|
if (lastException is not null)
|
|
{
|
|
throw lastException;
|
|
}
|
|
}
|
|
|
|
private static bool IsRetriable(Exception exception)
|
|
{
|
|
return exception is IOException or UnauthorizedAccessException;
|
|
}
|
|
}
|