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();
}
}
}
}
}
}