-
-
Save dampee/c9a904907f3c6bd1efb33b112b521baa to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Configuration; | |
using System.Linq; | |
using System.Reflection; | |
using System.Threading; | |
using System.Threading.Tasks; | |
using log4net; | |
namespace Utils | |
{ | |
public static class RetryHelper | |
{ | |
//I am using log4net but swap in your favourite | |
private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | |
public static async Task RetryOnExceptionAsync( | |
int times, TimeSpan delay, Func<Task> operation) | |
{ | |
await RetryOnExceptionAsync<Exception>(times, delay, operation); | |
} | |
public static async Task RetryOnExceptionAsync<TException>( | |
int times, TimeSpan delay, Func<Task> operation) where TException : Exception | |
{ | |
if (times <= 0) | |
throw new ArgumentOutOfRangeException(nameof(times)); | |
var attempts = 0; | |
do | |
{ | |
try | |
{ | |
attempts++; | |
await operation(); | |
break; | |
} | |
catch (TException ex) | |
{ | |
if (attempts == times) | |
throw; | |
await CreateDelayForException(times, attempts, delay, ex); | |
} | |
} while (true); | |
} | |
private static Task CreateDelayForException( | |
int times, int attempts, TimeSpan delay, Exception ex) | |
{ | |
var delay = IncreasingDelayInSeconds(attempts); | |
Log.Warn($"Exception on attempt {attempts} of {times}. " + | |
"Will retry after sleeping for {delay}.", ex); | |
return Task.Delay(delay); | |
} | |
internal static int[] DelayPerAttemptInSeconds = | |
{ | |
(int) TimeSpan.FromSeconds(2).TotalSeconds, | |
(int) TimeSpan.FromSeconds(30).TotalSeconds, | |
(int) TimeSpan.FromMinutes(2).TotalSeconds, | |
(int) TimeSpan.FromMinutes(10).TotalSeconds, | |
(int) TimeSpan.FromMinutes(30).TotalSeconds | |
}; | |
static int IncreasingDelayInSeconds(int failedAttempts) | |
{ | |
if (failedAttempts <= 0) throw new ArgumentOutOfRangeException(); | |
return failedAttempts > DelayPerAttemptInSeconds.Length ? DelayPerAttemptInSeconds.Last() : DelayPerAttemptInSeconds[failedAttempts]; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment