private async Task <object> ExecuteConsumer(TMessage msg, object message, object response, object consumerInstance)
        {
            if (_consumerWithContext && _consumerContextInitializer != null)
            {
                var consumerContext = new ConsumerContext();
                _consumerContextInitializer(msg, consumerContext);

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

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

            return(response);
        }
Exemplo n.º 2
0
        private async Task <Task> ExecuteConsumer(Type messageType, object message, byte[] messagePayload, ConsumerSettings consumerSettings)
        {
            var createMessageScope = IsMessageScopeEnabled(consumerSettings);

            if (createMessageScope)
            {
                _logger.LogDebug("Creating message scope for {message} of type {messageType}", message, consumerSettings.MessageType);
            }

            var messageScope = createMessageScope
                ? Settings.DependencyResolver.CreateScope()
                : Settings.DependencyResolver;

            try
            {
                MessageScope.Current = messageScope;

                // obtain the consumer from chosen DI container (root or scope)
                _logger.LogDebug("Resolving consumer type {consumerType}", consumerSettings.ConsumerType);
                var consumerInstance = messageScope.Resolve(consumerSettings.ConsumerType);
                if (consumerInstance == null)
                {
                    throw new ConfigurationMessageBusException($"The dependency resolver does not know how to create an instance of {consumerSettings.ConsumerType}");
                }

                Task consumerTask = null;
                try
                {
                    var messageForConsumer = !ProviderSettings.EnableMessageSerialization
                        ? message                                                        // prevent deep copy of the message
                        : consumerSettings.ConsumerMode == ConsumerMode.RequestResponse
                            ? DeserializeRequest(messageType, messagePayload, out var _) // will pass a deep copy of the message
                            : DeserializeMessage(messageType, messagePayload);           // will pass a deep copy of the message

                    _logger.LogDebug("Executing consumer instance {consumer} of type {consumerType} for message {message}", consumerInstance, consumerSettings.ConsumerType, message);
                    consumerTask = consumerSettings.ConsumerMethod(consumerInstance, messageForConsumer, consumerSettings.Topic);
                    await consumerTask.ConfigureAwait(false);
                }
                finally
                {
                    if (consumerSettings.IsDisposeConsumerEnabled && consumerInstance is IDisposable consumerInstanceDisposable)
                    {
                        _logger.LogDebug("Dosposing consumer instance {consumer} of type {consumerType}", consumerInstance, consumerSettings.ConsumerType);
                        consumerInstanceDisposable.DisposeSilently("ConsumerInstance", _logger);
                    }
                }


                return(consumerTask);
            }
            finally
            {
                MessageScope.Current = null;

                if (createMessageScope)
                {
                    _logger.LogDebug("Disposing message scope for {message} of type {messageType}", message, messageType);
                    messageScope.DisposeSilently("Scope", _logger);
                }
            }
        }
        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);
        }
Exemplo n.º 4
0
        public virtual async Task ProcessMessage(TMessage msg)
        {
            var msgPayload = _messagePayloadProvider(msg);

            MessageWithHeaders requestMessage = null;
            string             requestId      = null;
            DateTimeOffset?    expires        = null;

            _log.Debug("Deserializing message...");
            var message = _consumerSettings.IsRequestMessage
                ? _messageBus.DeserializeRequest(_consumerSettings.MessageType, msgPayload, out requestMessage)
                : _messageBus.Settings.Serializer.Deserialize(_consumerSettings.MessageType, msgPayload);

            if (requestMessage != null)
            {
                requestMessage.TryGetHeader(ReqRespMessageHeaders.RequestId, out requestId);
                requestMessage.TryGetHeader(ReqRespMessageHeaders.Expires, out expires);
            }

            // Verify if the request/message is already expired
            if (expires.HasValue)
            {
                var currentTime = _messageBus.CurrentTime;
                if (currentTime > expires.Value)
                {
                    _log.WarnFormat(CultureInfo.InvariantCulture, "The message arrived too late and is already expired (expires {0}, current {1})", expires.Value, currentTime);

                    try
                    {
                        // Execute the event hook
                        (_consumerSettings.OnMessageExpired ?? _messageBus.Settings.OnMessageExpired)?.Invoke(_consumerSettings, message);
                    }
                    catch (Exception eh)
                    {
                        // When the hook itself error out, catch the exception
                        _log.ErrorFormat(CultureInfo.InvariantCulture, "{0} method failed", eh, nameof(IConsumerEvents.OnMessageExpired));
                    }

                    // Do not process the expired message
                    return;
                }
            }

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

                // 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)
                {
                    _log.ErrorFormat(CultureInfo.InvariantCulture, "Handler execution failed", e);
                    // Save the exception
                    responseError = e.ToString();
                }
                else
                {
                    _log.ErrorFormat(CultureInfo.InvariantCulture, "Consumer execution failed", e);
                }

                try
                {
                    // Execute the event hook
                    (_consumerSettings.OnMessageFault ?? _messageBus.Settings.OnMessageFault)?.Invoke(_consumerSettings, message, e);
                }
                catch (Exception eh)
                {
                    // When the hook itself error out, catch the exception
                    _log.ErrorFormat(CultureInfo.InvariantCulture, "{0} method failed", eh, nameof(IConsumerEvents.OnMessageFault));
                }
            }
            finally
            {
                await _instancesQueue.SendAsync(consumerInstance).ConfigureAwait(false);
            }

            if (response != null || responseError != null)
            {
                // send the response (or error response)
                _log.DebugFormat(CultureInfo.InvariantCulture, "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);
            }
        }