ResilientUtils.cs 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041
  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 Retry<TOut>(Func<TOut> func, int maxAttempts = 2, int delayMs = 200, [CallerMemberName] string caller = "")
  17. => RetryOn<Exception, TOut>(func, maxAttempts, delayMs, caller);
  18. /// <summary>
  19. /// 在抛出特定异常时,延迟并自动重试。
  20. /// </summary>
  21. public static TOut RetryOn<TException, TOut>(Func<TOut> func, int maxAttempts = 2, int delayMs = 200, [CallerMemberName] string caller = "") where TException : Exception {
  22. int attempt = 0;
  23. while (true) {
  24. try {
  25. return func(); // 成功则退出
  26. } catch (TException ex) {
  27. attempt++;
  28. if (attempt < maxAttempts) {
  29. Logger.Warn(ex, $"第 {attempt} 次 {caller} 尝试失败,将在 {delayMs}ms 后重试");
  30. Thread.Sleep(delayMs);
  31. } else { // 超过最大尝试次数
  32. Logger.Warn(ex, $"第 {attempt} 次 {caller} 尝试失败,已到达最大尝试次数");
  33. throw;
  34. }
  35. }
  36. }
  37. }
  38. }