Ejemplo n.º 1
0
        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);
                }
            }
        }
Ejemplo n.º 2
0
 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);
        }
Ejemplo n.º 4
0
        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();
            }
        }