Advertisement
Hulkstance

Untitled

Oct 26th, 2022
1,088
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 3.22 KB | None | 0 0
  1. /// <summary>
  2. ///     This class provides Transient Fault Handling extension methods.
  3. /// </summary>
  4. internal static class Retry
  5. {
  6.     const string SleepDurationKey = "Broken";
  7.  
  8.     public static void Do(Action action, TimeSpan retryInterval, int retryCount = 3)
  9.     {
  10.         _ = Do<object?>(() =>
  11.         {
  12.             action();
  13.             return null;
  14.         }, retryInterval, retryCount);
  15.     }
  16.  
  17.     public static async Task DoAsync(Func<Task> action, TimeSpan retryInterval, int retryCount = 3)
  18.     {
  19.         _ = await DoAsync<object?>(async () =>
  20.         {
  21.             await action();
  22.             return null;
  23.         }, retryInterval, retryCount);
  24.     }
  25.  
  26.     public static T Do<T>(Func<T> action, TimeSpan retryInterval, int retryCount = 3)
  27.     {
  28.         var circuitBreakerPolicy = GetCircuitBreakerPolicy(retryCount);
  29.         var retryPolicy = GetRetryPolicy(retryInterval);
  30.  
  31.         var policyResult = Policy
  32.             .Wrap(retryPolicy, circuitBreakerPolicy)
  33.             .ExecuteAndCapture(action);
  34.  
  35.         if (policyResult.Outcome == OutcomeType.Failure)
  36.         {
  37.             throw policyResult.FinalException;
  38.         }
  39.  
  40.         return policyResult.Result;
  41.     }
  42.  
  43.     public static async Task<T> DoAsync<T>(Func<Task<T>> action, TimeSpan retryInterval, int retryCount = 3)
  44.     {
  45.         var circuitBreakerPolicy = GetCircuitBreakerPolicyAsync(retryCount);
  46.         var retryPolicy = GetRetryPolicyAsync(retryInterval);
  47.  
  48.         var policyResult = await Policy
  49.             .WrapAsync(retryPolicy, circuitBreakerPolicy)
  50.             .ExecuteAndCaptureAsync(action);
  51.  
  52.         if (policyResult.Outcome == OutcomeType.Failure)
  53.         {
  54.             throw policyResult.FinalException;
  55.         }
  56.  
  57.         return policyResult.Result;
  58.     }
  59.  
  60.     private static ISyncPolicy GetRetryPolicy(TimeSpan retryInterval)
  61.     {
  62.         return Policy
  63.             .Handle<Exception>()
  64.             .Or<BrokenCircuitException>()
  65.             .WaitAndRetryForever((_, ctx) =>
  66.                 ctx.ContainsKey(SleepDurationKey)
  67.                     ? (TimeSpan)ctx[SleepDurationKey]
  68.                     : retryInterval);
  69.     }
  70.  
  71.     private static ISyncPolicy GetCircuitBreakerPolicy(int retryCount)
  72.     {
  73.         return Policy
  74.             .Handle<Exception>()
  75.             .CircuitBreaker(retryCount, TimeSpan.FromMinutes(5),
  76.                 onBreak: (dr, ts, ctx) => { ctx[SleepDurationKey] = ts; },
  77.                 onReset: ctx => { ctx[SleepDurationKey] = null; });
  78.     }
  79.  
  80.     private static IAsyncPolicy GetRetryPolicyAsync(TimeSpan retryInterval)
  81.     {
  82.         return Policy
  83.             .Handle<Exception>()
  84.             .Or<BrokenCircuitException>()
  85.             .WaitAndRetryForeverAsync((_, ctx) =>
  86.                 ctx.ContainsKey(SleepDurationKey)
  87.                     ? (TimeSpan)ctx[SleepDurationKey]
  88.                     : retryInterval);
  89.     }
  90.  
  91.     private static IAsyncPolicy GetCircuitBreakerPolicyAsync(int retryCount)
  92.     {
  93.         return Policy
  94.             .Handle<Exception>()
  95.             .CircuitBreakerAsync(retryCount, TimeSpan.FromMinutes(5),
  96.                 onBreak: (dr, ts, ctx) => { ctx[SleepDurationKey] = ts; },
  97.                 onReset: ctx => { ctx[SleepDurationKey] = null; });
  98.     }
  99. }
  100.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement