// RabbitMQ retry that will publish a message to the retry queue.
        // Keep in mind that it might get processed by the other services using the same routing key and wildcards.
        private async Task <Acknowledgement> TryHandleWithRequeuingAsync <TMessage>(TMessage message,
                                                                                    CorrelationContext correlationContext,
                                                                                    Func <Task> handle, Func <TMessage, NextDoorException, IRejectedEvent> onError = null)
        {
            var messageName  = message.GetType().Name;
            var retryMessage = correlationContext.Retries == 0
                ? string.Empty
                : $"Retry: {correlationContext.Retries}'.";

            _logger.LogInformation($"Handling a message: '{messageName}' " +
                                   $"with correlation id: '{correlationContext.Id}'. {retryMessage}");

            try
            {
                await handle();

                _logger.LogInformation($"Handled a message: '{messageName}' " +
                                       $"with correlation id: '{correlationContext.Id}'. {retryMessage}");

                return(new Ack());
            }
            catch (Exception exception)
            {
                _logger.LogError(exception, exception.Message);
                if (exception is NextDoorException dShopException && onError != null)
                {
                    var rejectedEvent = onError(message, dShopException);
                    await _busClient.PublishAsync(rejectedEvent, ctx => ctx.UseMessageContext(correlationContext));

                    _logger.LogInformation($"Published a rejected event: '{rejectedEvent.GetType().Name}' " +
                                           $"for the message: '{messageName}' with correlation id: '{correlationContext.Id}'.");

                    return(new Ack());
                }

                if (correlationContext.Retries >= _retries)
                {
                    await _busClient.PublishAsync(RejectedEvent.For(messageName),
                                                  ctx => ctx.UseMessageContext(correlationContext));

                    throw new Exception($"Unable to handle a message: '{messageName}' " +
                                        $"with correlation id: '{correlationContext.Id}' " +
                                        $"after {correlationContext.Retries} retries.", exception);
                }

                _logger.LogInformation($"Unable to handle a message: '{messageName}' " +
                                       $"with correlation id: '{correlationContext.Id}', " +
                                       $"retry {correlationContext.Retries}/{_retries}...");

                return(Retry.In(TimeSpan.FromSeconds(_retryInterval)));
            }
        }
        // Internal retry for services that subscribe to the multiple events of the same types.
        // It does not interfere with the routing keys and wildcards (see TryHandleWithRequeuingAsync() below).
        private async Task <Acknowledgement> TryHandleAsync <TMessage>(TMessage message,
                                                                       CorrelationContext correlationContext,
                                                                       Func <Task> handle, Func <TMessage, NextDoorException, IRejectedEvent> onError = null)
        {
            var currentRetry = 0;
            var retryPolicy  = Policy
                               .Handle <Exception>()
                               .WaitAndRetryAsync(this._retries, i => TimeSpan.FromSeconds(this._retryInterval));

            var messageName = message.GetType().Name;

            return(await retryPolicy.ExecuteAsync <Acknowledgement>(async() =>
            {
                //var scope = this._tracer
                //    .BuildSpan("executing-handler")
                //    .AsChildOf(this._tracer.ActiveSpan)
                //    .StartActive(true);

                //using (scope)
                //{
                //var span = scope.Span;

                try
                {
                    var retryMessage = currentRetry == 0 ? string.Empty : $"Retry: {currentRetry}'.";

                    var preLogMessage = $"TryHandleAsync a message started: '{messageName}' " +
                                        $"with correlation id: '{correlationContext.Id}'. {retryMessage}";

                    this._logger.LogInformation(preLogMessage);
                    //span.Log(preLogMessage);

                    await handle();

                    var postLogMessage = $"TryHandleAsync a message completed: '{messageName}' " +
                                         $"with correlation id: '{correlationContext.Id}'. {retryMessage}";
                    this._logger.LogInformation(postLogMessage);
                    //span.Log(postLogMessage);

                    return new Ack();
                }
                catch (Exception exception)
                {
                    currentRetry++;
                    this._logger.LogError(exception, exception.Message);
                    //span.Log(exception.Message);
                    //span.SetTag(Tags.Error, true);

                    if (exception is NextDoorException nextDoorException && onError != null)
                    {
                        var rejectedEvent = onError(message, nextDoorException);
                        await this._busClient.PublishAsync(rejectedEvent, ctx => ctx.UseMessageContext(correlationContext));
                        this._logger.LogInformation($"Published a rejected event: '{rejectedEvent.GetType().Name}' " +
                                                    $"for the message: '{messageName}' with correlation id: '{correlationContext.Id}'.");
                        //span.SetTag("error-type", "domain");
                        return new Ack();
                    }

                    //span.SetTag("error-type", "infrastructure");
                    throw new Exception($"Unable to handle a message: '{messageName}' " +
                                        $"with correlation id: '{correlationContext.Id}', " +
                                        $"retry {currentRetry - 1}/{this._retries}...");
                }
                //}
            }));
        }