public override async Task InvokeAsync(IPipeContext context, CancellationToken token = default(CancellationToken))
        {
            var ack = GetMessageAcknowledgement(context);

            if (!(ack is Retry retryAck))
            {
                await Next.InvokeAsync(context, token);

                return;
            }

            var deadLeterExchangeName = GetDeadLetterExchangeName(retryAck.Span);
            await TopologyProvider.DeclareExchangeAsync(new ExchangeDeclaration
            {
                Name         = deadLeterExchangeName,
                Durable      = true,
                ExchangeType = ExchangeType.Direct
            });

            var deliveryArgs = GetDeliveryEventArgs(context);

            Logger.LogInformation("Message is marked for Retry. Will be published on exchange {exchangeName} with routing key {routingKey} in {retryIn}", deliveryArgs.Exchange, deliveryArgs.RoutingKey, retryAck.Span);
            UpdateRetryHeaders(deliveryArgs, context);
            var deadLetterQueueName = GetDeadLetterQueueName(deliveryArgs.Exchange, retryAck.Span);
            var deadLetterExchange  = context?.GetConsumerConfiguration()?.Exchange.Name ?? deliveryArgs.Exchange;
            await TopologyProvider.DeclareQueueAsync(new QueueDeclaration
            {
                Name      = deadLetterQueueName,
                Durable   = true,
                Arguments = new Dictionary <string, object>
                {
                    { QueueArgument.DeadLetterExchange, deadLetterExchange },
                    { QueueArgument.Expires, Convert.ToInt32(retryAck.Span.Add(TimeSpan.FromSeconds(1)).TotalMilliseconds) },
                    { QueueArgument.MessageTtl, Convert.ToInt32(retryAck.Span.TotalMilliseconds) }
                }
            });

            await TopologyProvider.BindQueueAsync(deadLetterQueueName, deadLeterExchangeName, deliveryArgs.RoutingKey, deliveryArgs.BasicProperties.Headers);

            using (var publishChannel = await ChannelFactory.CreateChannelAsync(token))
            {
                publishChannel.BasicPublish(deadLeterExchangeName, deliveryArgs.RoutingKey, false, deliveryArgs.BasicProperties, deliveryArgs.Body);
            }
            await TopologyProvider.UnbindQueueAsync(deadLetterQueueName, deadLeterExchangeName, deliveryArgs.RoutingKey, deliveryArgs.BasicProperties.Headers);

            context.Properties.AddOrReplace(PipeKey.MessageAcknowledgement, new Ack());
            await Next.InvokeAsync(context, token);
        }