private string OnMessageError(object message, Exception e, TMessage nativeMessage)
        {
            string responseError = null;

            if (_consumerSettings.ConsumerMode == ConsumerMode.RequestResponse)
            {
                _logger.LogError(e, "Handler execution failed");
                // Save the exception
                responseError = e.ToString();
            }
            else
            {
                _logger.LogError(e, "Consumer execution failed");
            }

            try
            {
                // Execute the event hook
                _consumerSettings.OnMessageFault?.Invoke(_messageBus, _consumerSettings, message, e, nativeMessage);
                _messageBus.Settings.OnMessageFault?.Invoke(_messageBus, _consumerSettings, message, e, nativeMessage);
            }
#pragma warning disable CA1031 // Intended, a catch all situation
            catch (Exception eh)
#pragma warning restore CA1031
            {
                MessageBusBase.HookFailed(_logger, eh, nameof(IConsumerEvents.OnMessageFault));
            }

            return(responseError);
        }
        private void OnMessageFinished(object message, TMessage nativeMessage)
        {
            try
            {
                // Execute the event hook
                _consumerSettings.OnMessageFinished?.Invoke(_messageBus, _consumerSettings, message, _consumerSettings.Topic, nativeMessage);
                _messageBus.Settings.OnMessageFinished?.Invoke(_messageBus, _consumerSettings, message, _consumerSettings.Topic, nativeMessage);
            }
#pragma warning disable CA1031 // Intended, a catch all situation
            catch (Exception eh)
#pragma warning restore CA1031
            {
                MessageBusBase.HookFailed(_logger, eh, nameof(IConsumerEvents.OnMessageFinished));
            }
        }
        private void OnMessageExpired(DateTimeOffset?expires, object message, DateTimeOffset currentTime, TMessage nativeMessage)
        {
            _logger.LogWarning("The message arrived too late and is already expired (expires {0}, current {1})", expires.Value, currentTime);

            try
            {
                // Execute the event hook
                _consumerSettings.OnMessageExpired?.Invoke(_messageBus, _consumerSettings, message, nativeMessage);
                _messageBus.Settings.OnMessageExpired?.Invoke(_messageBus, _consumerSettings, message, nativeMessage);
            }
#pragma warning disable CA1031 // Intended, a catch all situation
            catch (Exception eh)
#pragma warning restore CA1031
            {
                MessageBusBase.HookFailed(_logger, eh, nameof(IConsumerEvents.OnMessageExpired));
            }
        }
        public virtual async Task <Exception> ProcessMessage(TMessage msg)
        {
            Exception exceptionResult = null;

            try
            {
                DeserializeMessage(msg, out var requestMessage, out var requestId, out var expires, out var message);

                // Verify if the request/message is already expired
                if (expires != null)
                {
                    var currentTime = _messageBus.CurrentTime;
                    if (currentTime > expires.Value)
                    {
                        _logger.LogWarning("The message arrived too late and is already expired (expires {0}, current {1})", expires.Value, currentTime);

                        try
                        {
                            // Execute the event hook
                            _consumerSettings.OnMessageExpired?.Invoke(_messageBus, _consumerSettings, message, msg);
                            _messageBus.Settings.OnMessageExpired?.Invoke(_messageBus, _consumerSettings, message, msg);
                        }
                        catch (Exception eh)
                        {
                            MessageBusBase.HookFailed(_logger, eh, nameof(IConsumerEvents.OnMessageExpired));
                        }

                        // Do not process the expired message
                        return(null);
                    }
                }

                object response      = null;
                string responseError = null;

                var consumerInstance = await _instancesQueue.ReceiveAsync(_messageBus.CancellationToken).ConfigureAwait(false);

                try
                {
                    if (_consumerWithContext && _consumerContextInitializer != null)
                    {
                        var consumerContext = new ConsumerContext();
                        _consumerContextInitializer(msg, consumerContext);

                        var consumerWithContext = (IConsumerContextAware)consumerInstance;
                        consumerWithContext.Context.Value = consumerContext;
                    }

                    try
                    {
                        // Execute the event hook
                        _consumerSettings.OnMessageArrived?.Invoke(_messageBus, _consumerSettings, message, _consumerSettings.Topic, msg);
                        _messageBus.Settings.OnMessageArrived?.Invoke(_messageBus, _consumerSettings, message, _consumerSettings.Topic, msg);
                    }
                    catch (Exception eh)
                    {
                        MessageBusBase.HookFailed(_logger, eh, nameof(IConsumerEvents.OnMessageArrived));
                    }

                    // the consumer just subscribes to the message
                    var task = _consumerSettings.ConsumerMethod(consumerInstance, message, _consumerSettings.Topic);
                    await task.ConfigureAwait(false);

                    if (_consumerSettings.ConsumerMode == ConsumerMode.RequestResponse)
                    {
                        // the consumer handles the request (and replies)
                        response = _consumerSettings.ConsumerMethodResult(task);
                    }
                }
                catch (Exception e)
                {
                    if (_consumerSettings.ConsumerMode == ConsumerMode.RequestResponse)
                    {
                        _logger.LogError(e, "Handler execution failed");
                        // Save the exception
                        responseError = e.ToString();
                    }
                    else
                    {
                        _logger.LogError(e, "Consumer execution failed");
                    }

                    try
                    {
                        // Execute the event hook
                        _consumerSettings.OnMessageFault?.Invoke(_messageBus, _consumerSettings, message, e, msg);
                        _messageBus.Settings.OnMessageFault?.Invoke(_messageBus, _consumerSettings, message, e, msg);
                    }
                    catch (Exception eh)
                    {
                        MessageBusBase.HookFailed(_logger, eh, nameof(IConsumerEvents.OnMessageFault));
                    }

                    exceptionResult = e;
                }
                finally
                {
                    await _instancesQueue.SendAsync(consumerInstance).ConfigureAwait(false);
                }

                if (response != null || responseError != null)
                {
                    // send the response (or error response)
                    _logger.LogDebug("Serializing the response {0} of type {1} for RequestId: {2}...", response, _consumerSettings.ResponseType, requestId);

                    var responseMessage = new MessageWithHeaders();
                    responseMessage.SetHeader(ReqRespMessageHeaders.RequestId, requestId);
                    responseMessage.SetHeader(ReqRespMessageHeaders.Error, responseError);

                    await _messageBus.ProduceResponse(message, requestMessage, response, responseMessage, _consumerSettings).ConfigureAwait(false);
                }
            }
            catch (Exception e)
            {
                _logger.LogError(e, "Processing of the message {0} of type {1} failed", msg, _consumerSettings.MessageType);
                exceptionResult = e;
            }
            return(exceptionResult);
        }