async Task Attempt(RetryContext <TContext> retryContext, IPipe <TContext> next) { await retryContext.PreRetry().ConfigureAwait(false); await _observers.PreRetry(retryContext).ConfigureAwait(false); try { await next.Send(retryContext.Context).ConfigureAwait(false); } catch (Exception exception) { RetryContext <TContext> payloadRetryContext; if (retryContext.Context.TryGetPayload(out payloadRetryContext)) { await retryContext.RetryFaulted(exception).ConfigureAwait(false); await _observers.RetryFault(payloadRetryContext).ConfigureAwait(false); throw; } RetryContext genericRetryContext; if (retryContext.Context.TryGetPayload(out genericRetryContext)) { await retryContext.RetryFaulted(exception).ConfigureAwait(false); await _observers.RetryFault(genericRetryContext).ConfigureAwait(false); throw; } RetryContext <TContext> nextRetryContext; if (!retryContext.CanRetry(exception, out nextRetryContext)) { await nextRetryContext.RetryFaulted(exception).ConfigureAwait(false); await _observers.RetryFault(nextRetryContext).ConfigureAwait(false); retryContext.Context.GetOrAddPayload(() => nextRetryContext); throw; } await _observers.PostFault(nextRetryContext).ConfigureAwait(false); if (nextRetryContext.Delay.HasValue) { await Task.Delay(nextRetryContext.Delay.Value).ConfigureAwait(false); } await Attempt(nextRetryContext, next).ConfigureAwait(false); } }
async Task Attempt(TContext context, RetryContext <TContext> retryContext, IPipe <TContext> next) { while (retryContext.CancellationToken.IsCancellationRequested == false) { if (retryContext.Delay.HasValue) { await Task.Delay(retryContext.Delay.Value, retryContext.CancellationToken).ConfigureAwait(false); } await retryContext.PreRetry().ConfigureAwait(false); await _observers.PreRetry(retryContext).ConfigureAwait(false); try { await next.Send(retryContext.Context).ConfigureAwait(false); return; } catch (OperationCanceledException exception) when(exception.CancellationToken == retryContext.CancellationToken || exception.CancellationToken == context.CancellationToken) { throw; } catch (Exception exception) { if (context.CancellationToken.IsCancellationRequested) { context.CancellationToken.ThrowIfCancellationRequested(); } if (retryContext.Context.TryGetPayload(out RetryContext <TContext> payloadRetryContext)) { if (_retryPolicy.IsHandled(exception)) { await retryContext.RetryFaulted(exception).ConfigureAwait(false); await _observers.RetryFault(payloadRetryContext).ConfigureAwait(false); } context.GetOrAddPayload(() => payloadRetryContext); throw; } if (retryContext.Context.TryGetPayload(out RetryContext genericRetryContext)) { if (_retryPolicy.IsHandled(exception)) { await retryContext.RetryFaulted(exception).ConfigureAwait(false); await _observers.RetryFault(genericRetryContext).ConfigureAwait(false); } context.GetOrAddPayload(() => genericRetryContext); throw; } if (!retryContext.CanRetry(exception, out RetryContext <TContext> nextRetryContext)) { if (_retryPolicy.IsHandled(exception)) { await nextRetryContext.RetryFaulted(exception).ConfigureAwait(false); await _observers.RetryFault(nextRetryContext).ConfigureAwait(false); context.GetOrAddPayload(() => nextRetryContext); } throw; } await _observers.PostFault(nextRetryContext).ConfigureAwait(false); retryContext = nextRetryContext; } } context.CancellationToken.ThrowIfCancellationRequested(); }