コード例 #1
0
        public async Task <object> InvokeDispatcherAsync(MessageDispatchInfo dispatcher, IMessage message,
                                                         CancellationToken cancellationToken = default(CancellationToken))
        {
            Check.NotNull(dispatcher, nameof(dispatcher));
            Check.NotNull(message, nameof(message));

            if (!message.GetType().CanAssignTo(dispatcher.MessageType))
            {
                throw new ContainerException(
                          $"The message event type: {message.GetType()} being dispatched does not match or " +
                          $"derived from the dispatch information type of: {dispatcher.MessageType}.");
            }

            // Invoke the message consumers in a new lifetime scope.  This is for the case where a message
            // is received outside of the normal lifetime scope such as the one associated with the current
            // web request.
            using (var scope = AppContainer.Instance.Services.BeginLifetimeScope())
            {
                try
                {
                    // Resolve the component and call the message handler.
                    var consumer = (IMessageConsumer)scope.Resolve(dispatcher.ConsumerType);
                    return(await dispatcher.Dispatch(message, consumer, cancellationToken));
                }
                catch (Exception ex)
                {
                    Context.Logger.LogError(MessagingLogEvents.MESSAGING_EXCEPTION, "Message Dispatch Error Details.", ex);
                    throw;
                }
            }
        }
コード例 #2
0
        private void RpcConsumerReplyReceived(BasicDeliverEventArgs deliveryEvent)
        {
            ValidateRpcReply(deliveryEvent);

            // Determine the command type based on the type name stored in basic properties.  NOTE: a command type name is
            // just a value used to identify the type used to determine the C# class type on the receiving end corresponding
            // to the type on the caller's end.  They may or may not be the same physical C# type.
            string typeName    = deliveryEvent.BasicProperties.Type;
            Type   commandType = _brokerState.RpcTypes[typeName];

            // Dispatch the message the handler to obtain the result.
            MessageDispatchInfo dispatcher = _messagingModule.GetInProcessCommandDispatcher(commandType);
            IMessage            message    = _serializationMgr.Deserialize(commandType, deliveryEvent);
            object result = null;

            try
            {
                result = _messagingModule.InvokeDispatcherAsync(dispatcher, message).Result;

                // Publish the reply back to the publisher that made the request on the
                // queue specified by them in the message header on a new channel.
                PublishConsumerReply(result, deliveryEvent.BasicProperties);
            }
            catch (AggregateException ex)
            {
                PublishConsumerExceptionReply(ex.InnerException, deliveryEvent.BasicProperties);
            }
            catch (Exception ex)
            {
                PublishConsumerExceptionReply(ex, deliveryEvent.BasicProperties);
            }
        }
コード例 #3
0
        public MessageQueueSubscriber(string hostId, MessageDispatchInfo dispatchInfo)
        {
            if (string.IsNullOrWhiteSpace(hostId))
            {
                throw new ArgumentException("Value cannot be null or whitespace.", nameof(hostId));
            }

            if (dispatchInfo == null)
            {
                throw new ArgumentNullException(nameof(dispatchInfo));
            }

            _hostId = hostId;

            // Obtain the subscriber attribute so the definition metadata
            // can be retrieved.
            var queueAttribute = dispatchInfo.MessageHandlerMethod
                                 .GetCustomAttribute <SubscriberQueueAttribute>();

            DispatchInfo           = dispatchInfo;
            QueueMeta              = queueAttribute.QueueFactory.CreateQueueMeta(queueAttribute);
            QueueMeta.QueueFactory = queueAttribute.QueueFactory;

            ApplyScopedQueueName(QueueMeta);
        }
コード例 #4
0
        // Any dispatch corresponding to a method decorated with a
        // ChannelSubscriptionAttribute attribute will be bound to a channel.
        public static bool IsSubscriber(MessageDispatchInfo dispatchInfo)
        {
            if (dispatchInfo == null)
            {
                throw new ArgumentNullException(nameof(dispatchInfo));
            }

            return(dispatchInfo.MessageHandlerMethod.HasAttribute <ChannelSubscriptionAttribute>());
        }
コード例 #5
0
        // Any dispatch corresponding to a method decorated with a derived
        // HostItem attribute will be bound as a receiver.
        public static bool IsSubscriber(MessageDispatchInfo dispatchInfo)
        {
            if (dispatchInfo == null)
            {
                throw new ArgumentNullException(nameof(dispatchInfo));
            }

            return
                (dispatchInfo.MessageHandlerMethod.HasAttribute <HostItemAttribute>() &&
                 dispatchInfo.ConsumerType.HasAttribute <HostAttribute>());
        }
コード例 #6
0
        private void LogMessageReceiveEx(Exception ex, IMessage message, MessageDispatchInfo dispatchInfo)
        {
            var logger = LoggerFactory.CreateLogger <SubscriberLinkerBase>();

            logger.LogError(ex,
                            "Error handling received message of type: {MessageType} when calling " +
                            "the consumer: {Consumer} with handler: {Handler}.",
                            message.GetType(),
                            dispatchInfo.ConsumerType,
                            dispatchInfo.MessageHandlerMethod.Name);
        }
コード例 #7
0
        /// <summary>
        /// Dispatch Exception.
        /// </summary>
        /// <param name="message">Dispatch error message.</param>
        /// <param name="dispatchInfo">Describes how the message is to be dispatched when published.</param>
        /// <param name="innerException">The source exception.  If the exception is derived from
        /// NetFusionException, the detail will be added to this exception's details.</param>
        public MessageDispatchException(string message, MessageDispatchInfo dispatchInfo, Exception innerException)
            : base(message, innerException)
        {
            Check.NotNull(dispatchInfo, nameof(dispatchInfo));

            Details["DispatchInfo"] = new
            {
                MessageType   = dispatchInfo.MessageType.FullName,
                ConsumerType  = dispatchInfo.ConsumerType.FullName,
                HandlerMethod = dispatchInfo.MessageHandlerMethod.Name
            };
        }
コード例 #8
0
        /// <summary>
        /// Dispatch Exception.
        /// </summary>
        /// <param name="message">Dispatch error message.</param>
        /// <param name="dispatchInfo">Describes how the message is to be dispatched when published.</param>
        /// <param name="innerException">The source exception.  If the exception is derived from
        /// NetFusionException, the detail will be added to this exception's details.</param>
        public MessageDispatchException(string message, MessageDispatchInfo dispatchInfo, Exception innerException)
            : base(message, innerException)
        {
            if (dispatchInfo == null)
            {
                throw new ArgumentNullException(nameof(dispatchInfo));
            }

            Details["DispatchInfo"] = new
            {
                MessageType   = dispatchInfo.MessageType.FullName,
                ConsumerType  = dispatchInfo.ConsumerType.FullName,
                HandlerMethod = dispatchInfo.MessageHandlerMethod.Name
            };
        }
コード例 #9
0
        public MessageChannelSubscriber(MessageDispatchInfo dispatchInfo)
        {
            if (dispatchInfo == null)
            {
                throw new ArgumentNullException(nameof(dispatchInfo));
            }

            // Obtain the subscriber attribute so the metadata
            // can be retrieved.
            var channelAttrib = dispatchInfo.MessageHandlerMethod
                                .GetCustomAttribute <ChannelSubscriptionAttribute>();

            DispatchInfo = dispatchInfo;
            DatabaseName = channelAttrib.DatabaseName;
            Channel      = channelAttrib.Channel;
        }
コード例 #10
0
        private void LogReceivedExchangeMessage(IMessage message,
                                                MessageConsumer messageConsumer)
        {
            MessageDispatchInfo dispatchInfo = messageConsumer.DispatchInfo;

            _logger.LogTraceDetails(RabbitMqLogEvents.MESSAGE_CONSUMER, "Exchange Message Received",
                                    new
            {
                messageConsumer.BrokerName,
                messageConsumer.ExchangeName,
                messageConsumer.RouteKeys,
                dispatchInfo.ConsumerType,
                dispatchInfo.MessageType,

                MethodName = dispatchInfo.MessageHandlerMethod.Name,
                Message    = message
            });
        }
コード例 #11
0
        public MessageConsumer(
            BrokerAttribute brokerAttrib,
            QueueConsumerAttribute queueAttrib,
            MessageDispatchInfo dispatchInfo)
        {
            Check.NotNull(brokerAttrib, nameof(brokerAttrib));
            Check.NotNull(queueAttrib, nameof(queueAttrib));
            Check.NotNull(dispatchInfo, nameof(dispatchInfo));

            _brokerAttrib = brokerAttrib;
            _queueAttrib  = queueAttrib;
            _queueName    = _queueAttrib.QueueName;
            _routeKeys    = _queueAttrib.RouteKeys ?? new string[] { };

            MessageHandlers = new List <MessageHandler>();

            DispatchInfo = dispatchInfo;
        }
コード例 #12
0
        public async Task <object> InvokeDispatcherInNewLifetimeScopeAsync(MessageDispatchInfo dispatcher,
                                                                           IMessage message,
                                                                           CancellationToken cancellationToken = default)
        {
            if (dispatcher == null)
            {
                throw new ArgumentNullException(nameof(dispatcher));
            }
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }
            if (cancellationToken == null)
            {
                throw new ArgumentNullException(nameof(cancellationToken));
            }

            if (!message.GetType().CanAssignTo(dispatcher.MessageType))
            {
                throw new ContainerException(
                          $"The message event type: {message.GetType()} being dispatched does not match or " +
                          $"derive from the dispatch information type of: {dispatcher.MessageType}.");
            }

            // Invoke the message consumers in a new lifetime scope.  This is for the case where a message
            // is received outside of the normal lifetime scope such as the one associated with the current
            // web request.

            using (var scope = CompositeApp.Instance.CreateServiceScope())
            {
                try
                {
                    // Resolve the component and call the message handler.
                    var consumer = (IMessageConsumer)scope.ServiceProvider.GetRequiredService(dispatcher.ConsumerType);
                    return(await dispatcher.Dispatch(message, consumer, cancellationToken).ConfigureAwait(false));
                }
                catch (Exception ex)
                {
                    Context.Logger.LogError(MessagingLogEvents.MessagingException, ex, "Message Dispatch Error Details.");
                    throw;
                }
            }
        }
コード例 #13
0
        // When a RPC style command message is received, it is dispatched to the in-process handler having the
        // matching queue name and action-namespace.  This is unlike the other message patterns where a queue
        // is associated directly with only a single handler.  This allows for several RPC style commands to
        // use the same queue.  This allows for more efficient use of queues.
        public async Task OnMessageReceivedAsync(ConsumeContext context)
        {
            MessageDispatchInfo rpcCommandHandler = GetDispatchInfoForRpcCommand(context);
            var message = context.DeserializeIntoMessage(rpcCommandHandler.MessageType);

            context.LogReceivedMessage(message);

            try
            {
                object response = await context.MessagingModule.InvokeDispatcherInNewLifetimeScopeAsync(
                    rpcCommandHandler,
                    message).ConfigureAwait(false);

                await ReplyWithResponse(context, response);
            }
            catch (AggregateException ex)
            {
                await ReplyWithException(context, ex.InnerException);
            }
            catch (Exception ex)
            {
                await ReplyWithException(context, ex);
            }
        }
コード例 #14
0
 // The criteria that determines if a given consumer message handler method
 // is bound to a queue.
 private bool IsQueueConsumer(MessageDispatchInfo dispatchInfo)
 {
     return(dispatchInfo.ConsumerType.HasAttribute <BrokerAttribute>() &&
            dispatchInfo.MessageHandlerMethod.HasAttribute <QueueConsumerAttribute>());
 }
コード例 #15
0
 // Lookup the dispatch rules specified on the message consumer handler and
 // store a reference to the associated rule object.
 private void SetDispatchRule(MessageDispatchInfo dispatchInfo)
 {
     dispatchInfo.DispatchRules = DispatchRules
                                  .Where(r => dispatchInfo.DispatchRuleTypes.Contains(r.GetType()))
                                  .ToArray();
 }
コード例 #16
0
 public HostItemSubscriber(MessageDispatchInfo dispatchInfo)
 {
     DispatchInfo      = dispatchInfo ?? throw new ArgumentNullException(nameof(dispatchInfo));
     HostAttribute     = dispatchInfo.ConsumerType.GetAttribute <HostAttribute>();
     HostItemAttribute = dispatchInfo.MessageHandlerMethod.GetAttribute <HostItemAttribute>();
 }