ResilientUtils.cs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. namespace MeloongCore;
  2. public static class ResilientUtils {
  3. /// <summary>
  4. /// 在抛出任意异常时,延迟并自动重试。
  5. /// </summary>
  6. public static void Retry(Action action, int maxAttempts = 2, int delayMs = 200, [CallerMemberName] string caller = "")
  7. => RetryOn<Exception>(action, maxAttempts, delayMs, caller);
  8. /// <summary>
  9. /// 在抛出特定异常时,延迟并自动重试。
  10. /// </summary>
  11. public static void RetryOn<TException>(Action action, int maxAttempts = 2, int delayMs = 200, [CallerMemberName] string caller = "") where TException : Exception
  12. => RetryOn<TException, object?>(() => { action(); return null; }, maxAttempts, delayMs, caller);
  13. /// <summary>
  14. /// 在抛出特定异常时,延迟并自动重试。
  15. /// </summary>
  16. public static void RetryOn<TException1, TException2>(Action action, int maxAttempts = 2, int delayMs = 200, [CallerMemberName] string caller = "") where TException1 : Exception where TException2 : Exception
  17. => RetryOn<TException1, TException2, object?>(() => { action(); return null; }, maxAttempts, delayMs, caller);
  18. /// <summary>
  19. /// 在抛出任意异常时,延迟并自动重试。
  20. /// </summary>
  21. public static void Retry<TOut>(Func<TOut> func, int maxAttempts = 2, int delayMs = 200, [CallerMemberName] string caller = "")
  22. => RetryOn<Exception, TOut>(func, maxAttempts, delayMs, caller);
  23. /// <summary>
  24. /// 在抛出特定异常时,延迟并自动重试。
  25. /// </summary>
  26. public static TOut RetryOn<TException, TOut>(Func<TOut> func, int maxAttempts = 2, int delayMs = 200, [CallerMemberName] string caller = "") where TException : Exception {
  27. int attempt = 0;
  28. while (true) {
  29. try {
  30. return func(); // 成功则退出
  31. } catch (TException ex) {
  32. attempt++;
  33. if (attempt < maxAttempts) {
  34. Logger.Warn(ex, $"第 {attempt} 次 {caller} 尝试失败,将在 {delayMs}ms 后重试");
  35. Thread.Sleep(delayMs);
  36. } else { // 超过最大尝试次数
  37. Logger.Warn(ex, $"第 {attempt} 次 {caller} 尝试失败,已到达最大尝试次数");
  38. throw;
  39. }
  40. }
  41. }
  42. }
  43. /// <summary>
  44. /// 在抛出特定异常时,延迟并自动重试。
  45. /// </summary>
  46. public static TOut RetryOn<TException1, TException2, TOut>(Func<TOut> func, int maxAttempts = 2, int delayMs = 200, [CallerMemberName] string caller = "") where TException1 : Exception where TException2 : Exception {
  47. int attempt = 0;
  48. while (true) {
  49. try {
  50. return func(); // 成功则退出
  51. } catch (Exception ex) when (ex is TException1 or TException2) {
  52. attempt++;
  53. if (attempt < maxAttempts) {
  54. Logger.Warn(ex, $"第 {attempt} 次 {caller} 尝试失败,将在 {delayMs}ms 后重试");
  55. Thread.Sleep(delayMs);
  56. } else { // 超过最大尝试次数
  57. Logger.Warn(ex, $"第 {attempt} 次 {caller} 尝试失败,已到达最大尝试次数");
  58. throw;
  59. }
  60. }
  61. }
  62. }
  63. }