Beispiel #1
0
        public static async Task Retry(this IRetryPolicy retryPolicy, Func <Task> retryMethod, CancellationToken cancellationToken = default)
        {
            var inlinePipeContext = new InlinePipeContext(cancellationToken);

            RetryPolicyContext <InlinePipeContext> policyContext = retryPolicy.CreatePolicyContext(inlinePipeContext);

            try
            {
                await retryMethod().ConfigureAwait(false);
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (Exception exception)
            {
                if (!policyContext.CanRetry(exception, out RetryContext <InlinePipeContext> retryContext))
                {
                    throw;
                }

                try
                {
                    await Attempt(inlinePipeContext, retryContext, retryMethod).ConfigureAwait(false);

                    return;
                }
                catch (OperationCanceledException ex) when(ex.CancellationToken == cancellationToken)
                {
                }

                throw;
            }
            finally
            {
                policyContext.Dispose();
            }
        }
 Task IRetryObserver.PostCreate <T>(RetryPolicyContext <T> context)
 {
     return(TaskUtil.Completed);
 }
Beispiel #3
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 CommandContextRetryPolicyContext(RetryPolicyContext <CommandContext> policyContext, RetryCommandContext context)
 {
     _policyContext = policyContext;
     _context       = context;
 }
 public Task PostCreate <T>(RetryPolicyContext <T> context) where T : class, PipeContext => Task.CompletedTask;
        public virtual HttpResponse DoAction <T>(AcsRequest <T> request, bool autoRetry, int maxRetryNumber,
                                                 string regionId,
                                                 AlibabaCloudCredentials credentials, Signer signer, FormatType?format, List <Endpoint> endpoints)
            where T : AcsResponse
        {
            var                httpStatusCode    = "";
            var                retryAttemptTimes = 0;
            ClientException    exception;
            RetryPolicyContext retryPolicyContext;

            do
            {
                try
                {
                    var watch = Stopwatch.StartNew();

                    FormatType?requestFormatType = request.AcceptFormat;
                    format = requestFormatType;

                    var domain = request.ProductDomain ??
                                 Endpoint.FindProductDomain(regionId, request.Product, endpoints);

                    if (null == domain)
                    {
                        throw new ClientException("SDK.InvalidRegionId", "Can not find endpoint to access.");
                    }

                    request.Headers["User-Agent"] =
                        UserAgent.Resolve(request.GetSysUserAgentConfig(), userAgentConfig);
                    var httpRequest = request.SignRequest(signer, credentials, format, domain);
                    ResolveTimeout(httpRequest);
                    SetHttpsInsecure(IgnoreCertificate);
                    ResolveProxy(httpRequest, request);
                    var response = GetResponse(httpRequest);

                    httpStatusCode = response.Status.ToString();
                    PrintHttpDebugMsg(request, response);
                    watch.Stop();
                    CommonLog.ExecuteTime = watch.ElapsedMilliseconds;
                    return(response);
                }
                catch (ClientException ex)
                {
                    retryPolicyContext = new RetryPolicyContext(ex, httpStatusCode, retryAttemptTimes, request.Product,
                                                                request.Version,
                                                                request.ActionName, RetryCondition.BlankStatus);

                    CommonLog.LogException(ex, ex.ErrorCode, ex.ErrorMessage);
                    exception = ex;
                }

                Thread.Sleep(retryPolicy.GetDelayTimeBeforeNextRetry(retryPolicyContext));
            } while ((retryPolicy.ShouldRetry(retryPolicyContext) & RetryCondition.NoRetry) != RetryCondition.NoRetry);

            if (exception != null)
            {
                CommonLog.LogException(exception, exception.ErrorCode, exception.ErrorMessage);
                throw new ClientException(exception.ErrorCode, exception.ErrorMessage);
            }

            return(null);
        }
Beispiel #7
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)
            {
                RetryContext <ConsumeContext <T> > payloadRetryContext;
                if (context.TryGetPayload(out payloadRetryContext))
                {
                    await policyContext.RetryFaulted(exception).ConfigureAwait(false);

                    await _observers.RetryFault(payloadRetryContext).ConfigureAwait(false);

                    throw;
                }

                RetryContext genericRetryContext;
                if (context.TryGetPayload(out genericRetryContext))
                {
                    await policyContext.RetryFaulted(exception).ConfigureAwait(false);

                    await _observers.RetryFault(genericRetryContext).ConfigureAwait(false);

                    throw;
                }

                RetryContext <ConsumeContext <T> > retryContext;
                if (!policyContext.CanRetry(exception, out retryContext))
                {
                    await retryContext.RetryFaulted(exception).ConfigureAwait(false);

                    await _observers.RetryFault(retryContext).ConfigureAwait(false);

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

                        context.GetOrAddPayload(() => retryContext);
                        throw;
                    }
                }

                await _observers.PostFault(retryContext).ConfigureAwait(false);

                try
                {
                    MessageRedeliveryContext redeliveryContext;
                    if (!context.TryGetPayload(out 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);
                }
                catch (Exception redeliveryException)
                {
                    throw new ContextException("The message delivery could not be rescheduled", new AggregateException(redeliveryException, exception));
                }
            }
        }
Beispiel #8
0
 public RetryCondition ShouldRetry(RetryPolicyContext retryPolicyContext)
 {
     return(RetryCondition.NoRetry);
 }
Beispiel #9
0
 public RetryCondition ShouldRetry(RetryPolicyContext retryPolicyContext)
 {
     return(defaultRetryHttpStatusCodeList.Contains(retryPolicyContext.HttpStatusCode)
         ? RetryCondition.ShouldRetry
         : RetryCondition.NoRetry);
 }
        public static async Task Retry(this IHostConfiguration hostConfiguration, Func <Task> factory, ISupervisor supervisor,
                                       CancellationToken cancellationToken)
        {
            var description = hostConfiguration.HostAddress;

            using var tokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, supervisor.Stopping);

            var stoppingContext = new SupervisorStoppingContext(tokenSource.Token);

            RetryPolicyContext <SupervisorStoppingContext> policyContext = hostConfiguration.ReceiveTransportRetryPolicy.CreatePolicyContext(stoppingContext);

            try
            {
                RetryContext <SupervisorStoppingContext> retryContext = null;

                while (!tokenSource.Token.IsCancellationRequested)
                {
                    try
                    {
                        if (retryContext?.Delay != null)
                        {
                            await Task.Delay(retryContext.Delay.Value, tokenSource.Token).ConfigureAwait(false);
                        }

                        if (tokenSource.Token.IsCancellationRequested)
                        {
                            throw new ConnectionException($"The connection is stopping and cannot be used: {description}", retryContext?.Exception);
                        }

                        await factory().ConfigureAwait(false);

                        return;
                    }
                    catch (OperationCanceledException)
                    {
                        throw;
                    }
                    catch (Exception exception)
                    {
                        if (retryContext != null)
                        {
                            retryContext = retryContext.CanRetry(exception, out RetryContext <SupervisorStoppingContext> nextRetryContext)
                                ? nextRetryContext
                                : null;
                        }

                        if (retryContext == null && !policyContext.CanRetry(exception, out retryContext))
                        {
                            throw;
                        }
                    }

                    if (tokenSource.Token.IsCancellationRequested)
                    {
                        break;
                    }

                    try
                    {
                        await Task.Delay(TimeSpan.FromSeconds(1), tokenSource.Token).ConfigureAwait(false);
                    }
                    catch
                    {
                        // just a little breather before reconnecting the receive transport
                    }
                }

                throw new ConnectionException($"The connection is stopping and cannot be used: {description}", retryContext?.Exception);
            }
            finally
            {
                policyContext.Dispose();
            }
        }
Beispiel #11
0
 public int GetDelayTimeBeforeNextRetry(RetryPolicyContext retryPolicyContext)
 {
     return(0);
 }
        public virtual async Task <HttpResponse> DoActionAsync <T>(AcsRequest <T> request, bool autoRetry, int maxRetryNumber,
                                                                   string regionId,
                                                                   AlibabaCloudCredentials credentials, Signer signer, FormatType?format, List <Endpoint> endpoints,
                                                                   CancellationToken cancellationToken)
            where T : AcsResponse
        {
            var                httpStatusCode    = "";
            var                retryAttemptTimes = 0;
            ClientException    exception;
            RetryPolicyContext retryPolicyContext;

            do
            {
                try
                {
                    var watch = Stopwatch.StartNew();

                    FormatType?requestFormatType = request.AcceptFormat;

                    var domain = request.ProductDomain ??
                                 Endpoint.FindProductDomain(regionId, request.Product, endpoints);

                    if (null == domain)
                    {
                        throw new ClientException("SDK.InvalidRegionId", "Can not find endpoint to access.");
                    }

                    var userAgent = UserAgent.Resolve(request.GetSysUserAgentConfig(), userAgentConfig);
                    DictionaryUtil.Add(request.Headers, "User-Agent", userAgent);
                    DictionaryUtil.Add(request.Headers, "x-acs-version", request.Version);
                    if (!string.IsNullOrWhiteSpace(request.ActionName))
                    {
                        DictionaryUtil.Add(request.Headers, "x-acs-action", request.ActionName);
                    }
                    var httpRequest = request.SignRequest(signer, credentials, requestFormatType, domain);
                    ResolveTimeout(httpRequest, request.Product, request.Version, request.ActionName);
                    SetHttpsInsecure(IgnoreCertificate);
                    ResolveProxy(httpRequest, request);
                    var response = await GetResponseAsync(httpRequest, cancellationToken).ConfigureAwait(false);

                    httpStatusCode = response.Status.ToString();
                    PrintHttpDebugMsg(request, response);
                    watch.Stop();
                    CommonLog.ExecuteTime = watch.ElapsedMilliseconds;
                    return(response);
                }
                catch (ClientException ex)
                {
                    retryPolicyContext = new RetryPolicyContext(ex, httpStatusCode, retryAttemptTimes, request.Product,
                                                                request.Version,
                                                                request.ActionName, RetryCondition.BlankStatus);

                    CommonLog.LogException(ex, ex.ErrorCode, ex.ErrorMessage);
                    exception = ex;
                }

                await Task.Delay(retryPolicy.GetDelayTimeBeforeNextRetry(retryPolicyContext), cancellationToken).ConfigureAwait(false);
            } while ((retryPolicy.ShouldRetry(retryPolicyContext) & RetryCondition.NoRetry) != RetryCondition.NoRetry);

            if (exception != null)
            {
                CommonLog.LogException(exception, exception.ErrorCode, exception.ErrorMessage);
                throw new ClientException(exception.ErrorCode, exception.ErrorMessage);
            }

            return(null);
        }
        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();
            }
        }
Beispiel #14
0
 public ConsumeContextRetryPolicyContext(RetryPolicyContext <ConsumeContext> policyContext, RetryConsumeContext context, CancellationToken cancellationToken)
 {
     _policyContext     = policyContext;
     _context           = context;
     _cancellationToken = cancellationToken;
 }
        public override HttpResponse DoAction <T>(AcsRequest <T> request, bool autoRetry, int maxRetryNumber,
                                                  string regionId,
                                                  AlibabaCloudCredentials credentials, Signer signer, FormatType?format, List <Endpoint> endpoints)
        {
            var                httpStatusCode    = "";
            var                retryAttemptTimes = 0;
            ClientException    exception;
            RetryPolicyContext retryPolicyContext;

            do
            {
                try
                {
                    var watch = Stopwatch.StartNew();

                    FormatType?requestFormatType = request.AcceptFormat;
                    format = requestFormatType;

                    ProductDomain domain;
                    if (!string.IsNullOrEmpty(this.endpoint))
                    {
                        domain = new ProductDomain("", this.endpoint);
                    }
                    else
                    {
                        domain = request.ProductDomain ??
                                 Aliyun.Acs.Core.Regions.Endpoint.FindProductDomain(regionId, request.Product, endpoints);
                    }

                    if (null == domain)
                    {
                        throw new ClientException("SDK.InvalidRegionId", "Can not find endpoint to access.");
                    }

                    var userAgent = UserAgent.Resolve(request.GetSysUserAgentConfig(), userAgentConfig);
                    DictionaryUtil.Add(request.Headers, "User-Agent", userAgent);
                    DictionaryUtil.Add(request.Headers, "x-acs-version", request.Version);
                    if (!string.IsNullOrWhiteSpace(request.ActionName))
                    {
                        DictionaryUtil.Add(request.Headers, "x-acs-action", request.ActionName);
                    }

                    var httpRequest = SignRequest(request, signer, credentials, format, domain);
                    Helper.RunInstanceMethod(typeof(DefaultAcsClient), "ResolveTimeout", this, new object[] { httpRequest, request.Product, request.Version, request.ActionName });
                    SetHttpsInsecure(IgnoreCertificate);
                    ResolveProxy(httpRequest, request);
                    var response = GetResponse(httpRequest);

                    httpStatusCode = response.Status.ToString();
                    Helper.RunInstanceMethod(typeof(DefaultAcsClient), "PrintHttpDebugMsg", this, new object[] { request, response });
                    watch.Stop();
                    return(response);
                }
                catch (ClientException ex)
                {
                    retryPolicyContext = new RetryPolicyContext(ex, httpStatusCode, retryAttemptTimes, request.Product,
                                                                request.Version,
                                                                request.ActionName, RetryCondition.BlankStatus);

                    exception = ex;
                }

                Thread.Sleep(retryPolicy.GetDelayTimeBeforeNextRetry(retryPolicyContext));
            } while ((retryPolicy.ShouldRetry(retryPolicyContext) & RetryCondition.NoRetry) != RetryCondition.NoRetry);

            if (exception != null)
            {
                throw new ClientException(exception.ErrorCode, exception.ErrorMessage);
            }

            return(null);
        }
Beispiel #16
0
 public Task PostCreate <T>(RetryPolicyContext <T> context)
     where T : class, PipeContext
 {
     return(TaskUtil.Completed);
 }
Beispiel #17
0
 public Task PostCreate <T>(RetryPolicyContext <T> context)
     where T : class, PipeContext
 {
     return(ForEachAsync(x => x.PostCreate(context)));
 }
        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));
                    }
                }
            }
        }
Beispiel #19
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);
                }
            }
        }
            async Task Run()
            {
                var stoppingContext = new TransportStoppingContext(Stopping);

                RetryPolicyContext <TransportStoppingContext> policyContext = _retryPolicy.CreatePolicyContext(stoppingContext);

                try
                {
                    RetryContext <TransportStoppingContext> retryContext = null;

                    while (!IsStopping)
                    {
                        try
                        {
                            if (retryContext?.Delay != null)
                            {
                                await Task.Delay(retryContext.Delay.Value, Stopping).ConfigureAwait(false);
                            }

                            if (!IsStopping)
                            {
                                await RunTransport().ConfigureAwait(false);
                            }
                        }
                        catch (OperationCanceledException exception)
                        {
                            if (retryContext == null)
                            {
                                await NotifyFaulted(exception).ConfigureAwait(false);
                            }

                            throw;
                        }
                        catch (Exception exception)
                        {
                            if (retryContext != null)
                            {
                                retryContext = retryContext.CanRetry(exception, out RetryContext <TransportStoppingContext> nextRetryContext)
                                    ? nextRetryContext
                                    : null;
                            }

                            if (retryContext == null && !policyContext.CanRetry(exception, out retryContext))
                            {
                                break;
                            }
                        }

                        if (IsStopping)
                        {
                            break;
                        }

                        try
                        {
                            await Task.Delay(TimeSpan.FromSeconds(1), Stopping).ConfigureAwait(false);
                        }
                        catch
                        {
                            // just a little breather before reconnecting the receive transport
                        }
                    }
                }
                catch (OperationCanceledException exception)
                {
                    if (exception.CancellationToken != Stopping)
                    {
                        LogContext.Debug?.Log(exception, "ReceiveTransport Operation Cancelled: {InputAddress}", _context.InputAddress);
                    }
                }
                catch (Exception exception)
                {
                    LogContext.Debug?.Log(exception, "ReceiveTransport Run Exception: {InputAddress}", _context.InputAddress);
                }
                finally
                {
                    policyContext.Dispose();
                }
            }