<PackageReference Include="Polly" Version="5.9.0" />

RetryEngine

static class RetryEngine
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.ExceptionServices; using System.Threading; using System.Threading.Tasks; namespace Polly.Retry { internal static class RetryEngine { internal static TResult Implementation<TResult>(Func<Context, CancellationToken, TResult> action, Context context, CancellationToken cancellationToken, IEnumerable<ExceptionPredicate> shouldRetryExceptionPredicates, IEnumerable<ResultPredicate<TResult>> shouldRetryResultPredicates, Func<IRetryPolicyState<TResult>> policyStateFactory) { IRetryPolicyState<TResult> retryPolicyState = policyStateFactory(); TResult result; Exception ex; while (true) { cancellationToken.ThrowIfCancellationRequested(); try { result = (TResult)action(context, cancellationToken); if (!shouldRetryResultPredicates.Any((ResultPredicate<TResult> predicate) => predicate((TResult)result))) return (TResult)result; if (!retryPolicyState.CanRetry(new DelegateResult<TResult>((TResult)result), cancellationToken)) return (TResult)result; } catch (Exception ex2) { Exception ex3 = ex = ex2; Exception ex4 = (from predicate in shouldRetryExceptionPredicates select predicate(ex)).FirstOrDefault((Exception e) => e != null); if (ex4 == null) throw; if (!retryPolicyState.CanRetry(new DelegateResult<TResult>(ex4), cancellationToken)) { if (ex4 != ex) ExceptionDispatchInfo.Capture(ex4).Throw(); throw; } } } } internal static async Task<TResult> ImplementationAsync<TResult>(Func<Context, CancellationToken, Task<TResult>> action, Context context, CancellationToken cancellationToken, IEnumerable<ExceptionPredicate> shouldRetryExceptionPredicates, IEnumerable<ResultPredicate<TResult>> shouldRetryResultPredicates, Func<IRetryPolicyState<TResult>> policyStateFactory, bool continueOnCapturedContext) { IRetryPolicyState<TResult> policyState = policyStateFactory(); TResult result; Exception ex; while (true) { cancellationToken.ThrowIfCancellationRequested(); try { result = (TResult)(await action(context, cancellationToken).ConfigureAwait(continueOnCapturedContext)); if (!Enumerable.Any<ResultPredicate<TResult>>(shouldRetryResultPredicates, (Func<ResultPredicate<TResult>, bool>)((ResultPredicate<TResult> predicate) => predicate((TResult)result)))) return (TResult)result; if (!(await policyState.CanRetryAsync(new DelegateResult<TResult>((TResult)result), cancellationToken, continueOnCapturedContext).ConfigureAwait(continueOnCapturedContext))) return (TResult)result; } catch (Exception ex2) { ex = ex2; Exception handledException = Enumerable.FirstOrDefault<Exception>(Enumerable.Select<ExceptionPredicate, Exception>(shouldRetryExceptionPredicates, (Func<ExceptionPredicate, Exception>)((ExceptionPredicate predicate) => predicate(ex))), (Func<Exception, bool>)((Exception e) => e != null)); if (handledException == null) { Exception obj = ex2 as Exception; if (obj == null) throw ex2; ExceptionDispatchInfo.Capture(obj).Throw(); } if (!(await policyState.CanRetryAsync(new DelegateResult<TResult>(handledException), cancellationToken, continueOnCapturedContext).ConfigureAwait(continueOnCapturedContext))) { if (handledException != ex) ExceptionDispatchInfo.Capture(handledException).Throw(); Exception obj2 = ex2 as Exception; if (obj2 == null) throw ex2; ExceptionDispatchInfo.Capture(obj2).Throw(); } } } } } }