async Task IFilter <TContext> .Send(TContext context, IPipe <TContext> next) { using (RetryPolicyContext <TContext> policyContext = _retryPolicy.CreatePolicyContext(context)) { await _observers.PostCreate(policyContext).ConfigureAwait(false); try { await next.Send(policyContext.Context).ConfigureAwait(false); } catch (OperationCanceledException exception) when(exception.CancellationToken == policyContext.Context.CancellationToken || exception.CancellationToken == context.CancellationToken) { throw; } catch (Exception exception) { if (policyContext.Context.CancellationToken.IsCancellationRequested) { policyContext.Context.CancellationToken.ThrowIfCancellationRequested(); } if (policyContext.Context.TryGetPayload(out RetryContext <TContext> payloadRetryContext)) { if (_retryPolicy.IsHandled(exception)) { await policyContext.RetryFaulted(exception).ConfigureAwait(false); await _observers.RetryFault(payloadRetryContext).ConfigureAwait(false); } context.GetOrAddPayload(() => payloadRetryContext); throw; } if (policyContext.Context.TryGetPayload(out RetryContext genericRetryContext)) { if (_retryPolicy.IsHandled(exception)) { await policyContext.RetryFaulted(exception).ConfigureAwait(false); await _observers.RetryFault(genericRetryContext).ConfigureAwait(false); } context.GetOrAddPayload(() => genericRetryContext); throw; } if (!policyContext.CanRetry(exception, out RetryContext <TContext> retryContext)) { if (_retryPolicy.IsHandled(exception)) { await retryContext.RetryFaulted(exception).ConfigureAwait(false); await _observers.RetryFault(retryContext).ConfigureAwait(false); context.GetOrAddPayload(() => retryContext); } throw; } await _observers.PostFault(retryContext).ConfigureAwait(false); await Attempt(context, retryContext, next).ConfigureAwait(false); } } }
public bool IsHandled(Exception exception) { return(_retryPolicy.IsHandled(exception)); }
public virtual bool CanRetry(Exception exception, out RetryContext <TContext> retryContext) { retryContext = CreateRetryContext(exception, _cancellationTokenSource.Token); return(_policy.IsHandled(exception) && !_cancellationTokenSource.IsCancellationRequested); }
public async Task Send(ConsumeContext <T> context, IPipe <ConsumeContext <T> > next) { RetryPolicyContext <ConsumeContext <T> > policyContext = _retryPolicy.CreatePolicyContext(context); await _observers.PostCreate(policyContext).ConfigureAwait(false); try { await next.Send(policyContext.Context).ConfigureAwait(false); } catch (Exception exception) { if (context.CancellationToken.IsCancellationRequested) { if (exception is OperationCanceledException canceledException && canceledException.CancellationToken == context.CancellationToken) { throw; } context.CancellationToken.ThrowIfCancellationRequested(); } if (policyContext.Context.TryGetPayload(out RetryContext <ConsumeContext <T> > payloadRetryContext)) { await policyContext.RetryFaulted(exception).ConfigureAwait(false); await _observers.RetryFault(payloadRetryContext).ConfigureAwait(false); context.GetOrAddPayload(() => payloadRetryContext); throw; } if (policyContext.Context.TryGetPayload(out RetryContext genericRetryContext)) { await policyContext.RetryFaulted(exception).ConfigureAwait(false); await _observers.RetryFault(genericRetryContext).ConfigureAwait(false); context.GetOrAddPayload(() => genericRetryContext); throw; } if (!policyContext.CanRetry(exception, out RetryContext <ConsumeContext <T> > retryContext)) { await retryContext.RetryFaulted(exception).ConfigureAwait(false); await _observers.RetryFault(retryContext).ConfigureAwait(false); if (_retryPolicy.IsHandled(exception)) { context.GetOrAddPayload(() => retryContext); } throw; } int previousDeliveryCount = context.Headers.Get(MessageHeaders.RedeliveryCount, default(int?)) ?? 0; for (int retryIndex = 0; retryIndex < previousDeliveryCount; retryIndex++) { if (!retryContext.CanRetry(exception, out retryContext)) { await retryContext.RetryFaulted(exception).ConfigureAwait(false); await _observers.RetryFault(retryContext).ConfigureAwait(false); if (_retryPolicy.IsHandled(exception)) { context.GetOrAddPayload(() => retryContext); } throw; } } await _observers.PostFault(retryContext).ConfigureAwait(false); try { if (!context.TryGetPayload(out MessageRedeliveryContext redeliveryContext)) { throw new ContextException("The message redelivery context was not available to delay the message", exception); } var delay = retryContext.Delay ?? TimeSpan.Zero; await redeliveryContext.ScheduleRedelivery(delay).ConfigureAwait(false); await context.NotifyConsumed(context, context.ReceiveContext.ElapsedTime, TypeMetadataCache <RedeliveryRetryFilter <T> > .ShortName).ConfigureAwait(false); } catch (Exception redeliveryException) { throw new ContextException("The message delivery could not be rescheduled", new AggregateException(redeliveryException, exception)); } } }
public async Task Send(TContext context, IPipe <TContext> next) { using (RetryPolicyContext <TContext> policyContext = _retryPolicy.CreatePolicyContext(context)) { if (_observers.Count > 0) { await _observers.PostCreate(policyContext).ConfigureAwait(false); } try { await next.Send(policyContext.Context).ConfigureAwait(false); } catch (OperationCanceledException exception) when(exception.CancellationToken == context.CancellationToken || exception.CancellationToken == policyContext.Context.CancellationToken) { throw; } catch (Exception exception) { if (policyContext.Context.CancellationToken.IsCancellationRequested) { policyContext.Context.CancellationToken.ThrowIfCancellationRequested(); } if (!policyContext.CanRetry(exception, out RetryContext <TContext> retryContext)) { if (_retryPolicy.IsHandled(exception)) { context.GetOrAddPayload(() => retryContext); await retryContext.RetryFaulted(exception).ConfigureAwait(false); if (_observers.Count > 0) { await _observers.RetryFault(retryContext).ConfigureAwait(false); } } throw; } var previousDeliveryCount = context.GetRedeliveryCount(); for (var retryIndex = 0; retryIndex < previousDeliveryCount; retryIndex++) { if (!retryContext.CanRetry(exception, out retryContext)) { if (_retryPolicy.IsHandled(exception)) { context.GetOrAddPayload(() => retryContext); await retryContext.RetryFaulted(exception).ConfigureAwait(false); if (_observers.Count > 0) { await _observers.RetryFault(retryContext).ConfigureAwait(false); } } throw; } } if (_observers.Count > 0) { await _observers.PostFault(retryContext).ConfigureAwait(false); } try { var redeliveryContext = context.GetPayload <MessageRedeliveryContext>(); var delay = retryContext.Delay ?? TimeSpan.Zero; await redeliveryContext.ScheduleRedelivery(delay).ConfigureAwait(false); await context.NotifyConsumed(context, context.ReceiveContext.ElapsedTime, TypeMetadataCache <RedeliveryRetryFilter <TContext, TMessage> > .ShortName).ConfigureAwait(false); } catch (Exception redeliveryException) { throw new TransportException(context.ReceiveContext.InputAddress, "The message delivery could not be rescheduled", new AggregateException(redeliveryException, exception)); } } } }
async Task RunJob(PipeContext context, IJobConsumer <TJob> jobConsumer) { var jobContext = context.GetPayload <JobContext <TJob> >(); RetryPolicyContext <JobContext <TJob> > policyContext = _retryPolicy.CreatePolicyContext(jobContext); try { await jobContext.NotifyStarted().ConfigureAwait(false); await jobConsumer.Run(jobContext).ConfigureAwait(false); await jobContext.NotifyCompleted().ConfigureAwait(false); } catch (OperationCanceledException exception) { if (jobContext.CancellationToken == exception.CancellationToken) { await jobContext.NotifyCanceled("Operation canceled").ConfigureAwait(false); } } catch (Exception exception) { if (!policyContext.CanRetry(exception, out RetryContext <JobContext <TJob> > retryContext)) { if (_retryPolicy.IsHandled(exception)) { context.GetOrAddPayload(() => retryContext); await retryContext.RetryFaulted(exception).ConfigureAwait(false); } await jobContext.NotifyFaulted(exception).ConfigureAwait(false); return; } var currentRetryAttempt = jobContext.RetryAttempt; for (var retryIndex = 0; retryIndex < currentRetryAttempt; retryIndex++) { if (!retryContext.CanRetry(exception, out retryContext)) { if (_retryPolicy.IsHandled(exception)) { context.GetOrAddPayload(() => retryContext); await retryContext.RetryFaulted(exception).ConfigureAwait(false); } await jobContext.NotifyFaulted(exception).ConfigureAwait(false); return; } } var delay = retryContext.Delay ?? TimeSpan.Zero; await jobContext.NotifyFaulted(exception, delay).ConfigureAwait(false); } finally { policyContext.Dispose(); } }