/// <summary> /// Create a retry policy /// </summary> /// <param name="policy">Retry policy to use</param> /// <param name="options">Retry policy options</param> /// <returns></returns> public static IRetryPolicy Create(RetryPolicy policy, RetryPolicyOptions options) { switch (policy) { case RetryPolicy.ExponentialBackoff: return(new ExponentialBackoffPolicy(options)); case RetryPolicy.EasedBackoff: return(new EasedBackoffPolicy(options)); default: return(new StaticDelayPolicy(options)); } }
/// <summary> /// Perform an synchronous retry up to the maximum specified limit /// </summary> /// <param name="action"></param> /// <param name="retryInterval">How often to perform the retry.</param> /// <param name="retryLimit">The maximum number of times to retry</param> /// <param name="retryPolicy">The retry policy to apply</param> /// <param name="retryPolicyOptions">Options to specify further configuration for a retry policy</param> /// <exception cref="RetryTimeoutException"></exception> public static void Do(RetryAction action, TimeSpan retryInterval, int retryLimit, RetryPolicy retryPolicy, RetryPolicyOptions retryPolicyOptions) => Do((iteration, max) => action.Invoke(), retryInterval, retryLimit, retryPolicy, retryPolicyOptions, null, null);
/// <summary> /// Perform a synchronous retry up to the maximum specified limit /// </summary> /// <typeparam name="T"></typeparam> /// <param name="action">The Action to call that will be retried until successful.</param> /// <param name="retryInterval">How often to perform the retry.</param> /// <param name="retryLimit">The maximum number of times to retry</param> /// <param name="onFailure">Will be called upon an exception thrown</param> /// <param name="retryPolicy">The retry policy to apply</param> /// <param name="retryPolicyOptions">The options to provide your retry policy</param> /// <param name="mustReturnTrueBeforeFail">Must evaluate to true for retry to fail</param> /// <param name="exceptionTypes">A list of exceptions that will be retried gracefully. All other exceptions will be rethrown.</param> /// <exception cref="RetryTimeoutException"></exception> /// <returns></returns> public static T Do <T>(RetryActionWithParametersAndResult <T> action, TimeSpan retryInterval, int retryLimit, RetryPolicy retryPolicy, RetryPolicyOptions retryPolicyOptions, Action <Exception, int, int> onFailure, Func <bool> mustReturnTrueBeforeFail, params Type[] exceptionTypes) => PerformAction((x, y) => action.Invoke(x, y), retryInterval, retryLimit, retryPolicy, retryPolicyOptions, onFailure, mustReturnTrueBeforeFail, exceptionTypes);
/// <summary> /// Perform a synchronous retry up to the maximum specified limit /// </summary> /// <param name="action">The Action to call that will be retried until successful.</param> /// <param name="retryInterval">How often to perform the retry.</param> /// <param name="retryLimit">The maximum number of times to retry</param> /// <param name="onFailure">Will be called upon an exception thrown</param> /// <param name="mustReturnTrueBeforeFail">Must evaluate to true for retry to fail. Evaluating to false will retry infinitely until true.</param> /// <param name="retryPolicy">The retry policy to apply</param> /// <param name="retryPolicyOptions">The options to provide your retry policy</param> /// <param name="exceptionTypes">A list of exceptions that will be retried gracefully. All other exceptions will be rethrown.</param> /// <exception cref="RetryTimeoutException"></exception> public static void Do(RetryActionWithParameters action, TimeSpan retryInterval, int retryLimit, RetryPolicy retryPolicy, RetryPolicyOptions retryPolicyOptions, Action <Exception, int, int> onFailure, Func <bool> mustReturnTrueBeforeFail, params Type[] exceptionTypes) => PerformAction <object>((x, y) => { action.Invoke(x, y); return(null); }, retryInterval, retryLimit, retryPolicy, retryPolicyOptions, onFailure, mustReturnTrueBeforeFail, exceptionTypes);
/// <summary> /// Perform an synchronous retry up to the maximum specified limit /// </summary> /// <typeparam name="T"></typeparam> /// <param name="action"></param> /// <param name="retryInterval">How often to perform the retry.</param> /// <param name="retryLimit">The maximum number of times to retry</param> /// <param name="retryPolicy">The retry policy to apply</param> /// <param name="retryPolicyOptions">Options to specify further configuration for a retry policy</param> /// <exception cref="RetryTimeoutException"></exception> /// <returns></returns> public static T Do <T>(RetryActionWithParametersAndResult <T> action, TimeSpan retryInterval, int retryLimit, RetryPolicy retryPolicy, RetryPolicyOptions retryPolicyOptions) => Do(action, retryInterval, retryLimit, retryPolicy, retryPolicyOptions, null, null);
/// <summary> /// Perform an synchronous retry up to the maximum specified limit /// </summary> /// <param name="action"></param> /// <param name="retryInterval">How often to perform the retry.</param> /// <param name="retryLimit">The maximum number of times to retry</param> /// <param name="retryPolicy">The retry policy to apply</param> /// <param name="retryPolicyOptions">Options to specify further configuration for a retry policy</param> /// <exception cref="RetryTimeoutException"></exception> public static void Do(RetryActionWithParameters action, TimeSpan retryInterval, int retryLimit, RetryPolicy retryPolicy, RetryPolicyOptions retryPolicyOptions) => Do(action, retryInterval, retryLimit, retryPolicy, retryPolicyOptions, null, null);
private static async Task <T> PerformActionAsync <T>(RetryActionWithParametersAndResultAsync <T> action, TimeSpan retryInterval, int retryLimit, RetryPolicy retryPolicy, RetryPolicyOptions retryPolicyOptions, CancellationToken?cancellationToken, Action <Exception, int, int> onFailure, Func <bool> mustReturnTrueBeforeFail, params Type[] exceptionTypes) { var exceptions = new List <Exception>(); var startTime = DateTime.Now; var retryIteration = 0; do { try { // invoke the action return(await InvokeAsync(action, retryIteration, retryLimit, cancellationToken)); } catch (Exception ex) { exceptions.Add(ex); await HandleExceptionAsync(ex, startTime, retryInterval, retryIteration, retryLimit, retryPolicy, retryPolicyOptions, onFailure, exceptionTypes); } retryIteration++; } while (MustContinue(mustReturnTrueBeforeFail) || (retryIteration < retryLimit && (!cancellationToken.HasValue || !cancellationToken.Value.IsCancellationRequested))); throw new RetryTimeoutException(exceptions, retryLimit); }
private static async Task WaitOrThrowAsync(Exception ex, DateTime startTime, TimeSpan retryInterval, int retryIteration, int retryLimit, RetryPolicy retryPolicy, RetryPolicyOptions retryPolicyOptions, params Type[] exceptionTypes) { if (exceptionTypes == null || exceptionTypes.Length == 0 || exceptionTypes.Contains(ex.GetType())) { if (retryIteration - 1 < retryLimit) { var sleepValue = RetryPolicyFactory .Create(retryPolicy, retryPolicyOptions) .ApplyPolicy(RetryParameters.Create(startTime, retryInterval, retryIteration, retryLimit)); if (sleepValue.TotalMilliseconds < 0) { throw new ArgumentOutOfRangeException(); } // use Task.Delay for asynchronous waits await Task.Delay(sleepValue); } } else { throw ex; } }
private static async Task HandleExceptionAsync(Exception ex, DateTime startTime, TimeSpan retryInterval, int retryIteration, int retryLimit, RetryPolicy retryPolicy, RetryPolicyOptions retryPolicyOptions, Func <Exception, int, int, Task> onFailure, params Type[] exceptionTypes) { await Task.Yield(); if (onFailure != null) { await onFailure(ex, retryIteration, retryLimit); } await WaitOrThrowAsync(ex, startTime, retryInterval, retryIteration, retryLimit, retryPolicy, retryPolicyOptions, exceptionTypes); }
private static async Task HandleExceptionAsync(Exception ex, DateTime startTime, TimeSpan retryInterval, int retryIteration, int retryLimit, RetryPolicy retryPolicy, RetryPolicyOptions retryPolicyOptions, Action <Exception, int, int> onFailure, params Type[] exceptionTypes) { await Task.Yield(); onFailure?.Invoke(ex, retryIteration, retryLimit); await WaitOrThrowAsync(ex, startTime, retryInterval, retryIteration, retryLimit, retryPolicy, retryPolicyOptions, exceptionTypes); }
private static T PerformAction <T>(RetryActionWithParametersAndResult <T> action, TimeSpan retryInterval, int retryLimit, RetryPolicy retryPolicy, RetryPolicyOptions retryPolicyOptions, Action <Exception, int, int> onFailure, Func <bool> mustReturnTrueBeforeFail, params Type[] exceptionTypes) { var exceptions = new List <Exception>(); var startTime = DateTime.Now; var retryIteration = 0; do { try { // invoke the action return(action(retryIteration, retryLimit)); } catch (Exception ex) { exceptions.Add(ex); HandleException(ex, startTime, retryInterval, retryIteration, retryLimit, retryPolicy, retryPolicyOptions, onFailure, exceptionTypes); } retryIteration++; } while (MustContinue(mustReturnTrueBeforeFail) || retryIteration < retryLimit); throw new RetryTimeoutException(exceptions, retryLimit); }