コード例 #1
0
        protected void ConsumeMessage(BrokeredMessage brokeredMessage)
        {
            var eventContext        = new MessageContext(brokeredMessage);
            var message             = eventContext.Message;
            var messageHandlerTypes = _handlerProvider.GetHandlerTypes(message.GetType());

            if (messageHandlerTypes.Count == 0)
            {
                return;
            }

            messageHandlerTypes.ForEach(messageHandlerType =>
            {
                PerMessageContextLifetimeManager.CurrentMessageContext = eventContext;
                eventContext.ToBeSentMessageContexts.Clear();
                var messageStore     = IoCFactory.Resolve <IMessageStore>();
                var subscriptionName = string.Format("{0}.{1}", _subscriptionName, messageHandlerType.FullName);
                if (!messageStore.HasEventHandled(eventContext.MessageID, subscriptionName))
                {
                    try
                    {
                        var messageHandler = IoCFactory.Resolve(messageHandlerType);
                        ((dynamic)messageHandler).Handle((dynamic)message);
                        var commandContexts = eventContext.ToBeSentMessageContexts;
                        var eventBus        = IoCFactory.Resolve <IEventBus>();
                        var messageContexts = new List <MessageContext>();
                        eventBus.GetMessages().ForEach(msg => messageContexts.Add(new MessageContext(msg)));
                        messageStore.SaveEvent(eventContext, subscriptionName, commandContexts, messageContexts);
                        if (commandContexts.Count > 0)
                        {
                            ((CommandBus)IoCFactory.Resolve <ICommandBus>()).SendCommands(commandContexts.AsEnumerable());
                        }
                        if (messageContexts.Count > 0)
                        {
                            IoCFactory.Resolve <IEventPublisher>().Publish(messageContexts.ToArray());
                        }
                    }
                    catch (Exception e)
                    {
                        if (e is DomainException)
                        {
                            _logger.Warn(message.ToJson(), e);
                        }
                        else
                        {
                            //IO error or sytem Crash
                            _logger.Error(message.ToJson(), e);
                        }
                        messageStore.SaveFailHandledEvent(eventContext, subscriptionName, e);
                    }
                    finally
                    {
                        PerMessageContextLifetimeManager.CurrentMessageContext = null;
                    }
                }
            });
        }
コード例 #2
0
        protected async Task ConsumeMessage(IMessageContext eventContext)
        {
            try
            {
                _logger?.Debug($"start handle event {_consumerId} {eventContext.Message.ToJson()}");

                var message             = eventContext.Message;
                var sagaInfo            = eventContext.SagaInfo;
                var messageHandlerTypes = _handlerProvider.GetHandlerTypes(message.GetType());

                if (messageHandlerTypes.Count == 0)
                {
                    _logger?.Debug($"event has no handlerTypes, message:{message.ToJson()}");
                    _internalConsumer.CommitOffset(eventContext);
                    return;
                }

                //messageHandlerTypes.ForEach(messageHandlerType =>
                foreach (var messageHandlerType in messageHandlerTypes)
                {
                    using (var scope = IoCFactory.Instance.CurrentContainer.CreateChildContainer())
                    {
                        scope.RegisterInstance(typeof(IMessageContext), eventContext);
                        var messageStore     = scope.Resolve <IMessageStore>();
                        var subscriptionName = $"{_subscriptionName}.{messageHandlerType.Type.FullName}";
                        if (!messageStore.HasEventHandled(eventContext.MessageID, subscriptionName))
                        {
                            var eventMessageStates   = new List <MessageState>();
                            var commandMessageStates = new List <MessageState>();
                            var eventBus             = scope.Resolve <IEventBus>();
                            try
                            {
                                var messageHandler = scope.Resolve(messageHandlerType.Type);
                                using (var transactionScope = new TransactionScope(TransactionScopeOption.Required,
                                                                                   new TransactionOptions
                                {
                                    IsolationLevel = IsolationLevel.ReadCommitted
                                },
                                                                                   TransactionScopeAsyncFlowOption.Enabled))
                                {
                                    if (messageHandlerType.IsAsync)
                                    {
                                        await((dynamic)messageHandler).Handle((dynamic)message)
                                        .ConfigureAwait(false);
                                    }
                                    else
                                    {
                                        await Task.Run(() => { ((dynamic)messageHandler).Handle((dynamic)message); })
                                        .ConfigureAwait(false);
                                    }

                                    //get commands to be sent
                                    eventBus.GetCommands()
                                    .ForEach(cmd =>
                                             commandMessageStates.Add(new MessageState(_commandBus?.WrapCommand(cmd,
                                                                                                                sagaInfo: sagaInfo, producer: Producer)))
                                             );
                                    //get events to be published
                                    eventBus.GetEvents()
                                    .ForEach(msg =>
                                    {
                                        var topic = msg.GetFormatTopic();
                                        eventMessageStates.Add(new MessageState(_messageQueueClient.WrapMessage(msg,
                                                                                                                topic: topic,
                                                                                                                key: msg.Key, sagaInfo: sagaInfo, producer: Producer)));
                                    });

                                    eventBus.GetToPublishAnywayMessages()
                                    .ForEach(msg =>
                                    {
                                        var topic = msg.GetFormatTopic();
                                        eventMessageStates.Add(new MessageState(_messageQueueClient.WrapMessage(msg,
                                                                                                                topic: topic, key: msg.Key,
                                                                                                                sagaInfo: sagaInfo, producer: Producer)));
                                    });

                                    eventMessageStates.AddRange(GetSagaReplyMessageStates(sagaInfo, eventBus));

                                    messageStore.HandleEvent(eventContext,
                                                             subscriptionName,
                                                             commandMessageStates.Select(s => s.MessageContext),
                                                             eventMessageStates.Select(s => s.MessageContext));

                                    transactionScope.Complete();
                                }
                                if (commandMessageStates.Count > 0)
                                {
                                    _commandBus?.SendMessageStates(commandMessageStates);
                                }
                                if (eventMessageStates.Count > 0)
                                {
                                    _messagePublisher?.SendAsync(eventMessageStates.ToArray());
                                }
                            }
                            catch (Exception e)
                            {
                                eventMessageStates.Clear();
                                messageStore.Rollback();
                                if (e is DomainException)
                                {
                                    var domainExceptionEvent = ((DomainException)e).DomainExceptionEvent;
                                    if (domainExceptionEvent != null)
                                    {
                                        var topic            = domainExceptionEvent.GetFormatTopic();
                                        var exceptionMessage = _messageQueueClient.WrapMessage(domainExceptionEvent,
                                                                                               eventContext.MessageID,
                                                                                               topic,
                                                                                               producer: Producer);
                                        eventMessageStates.Add(new MessageState(exceptionMessage));
                                    }
                                    _logger?.Warn(message.ToJson(), e);
                                }
                                else
                                {
                                    //IO error or sytem Crash
                                    //if we meet with unknown exception, we interrupt saga
                                    if (sagaInfo != null)
                                    {
                                        eventBus.FinishSaga(e);
                                    }
                                    _logger?.Error(message.ToJson(), e);
                                }

                                eventBus.GetToPublishAnywayMessages()
                                .ForEach(msg =>
                                {
                                    var topic = msg.GetFormatTopic();
                                    eventMessageStates.Add(new MessageState(_messageQueueClient.WrapMessage(msg,
                                                                                                            topic: topic, key: msg.Key, sagaInfo: sagaInfo, producer: Producer)));
                                });

                                eventMessageStates.AddRange(GetSagaReplyMessageStates(sagaInfo, eventBus));

                                messageStore.SaveFailHandledEvent(eventContext, subscriptionName, e,
                                                                  eventMessageStates.Select(s => s.MessageContext).ToArray());
                                if (eventMessageStates.Count > 0)
                                {
                                    _messagePublisher?.SendAsync(eventMessageStates.ToArray());
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                _logger?.Fatal($"Handle event failed event: {eventContext.ToJson()}", e);
            }
            _internalConsumer.CommitOffset(eventContext);
        }
コード例 #3
0
        protected async virtual Task ConsumeMessage(IMessageContext commandContext)
        {
            var             command      = commandContext.Message as ICommand;
            var             needReply    = !string.IsNullOrEmpty(commandContext.ReplyToEndPoint);
            var             sagaInfo     = commandContext.SagaInfo;
            IMessageContext messageReply = null;

            if (command == null)
            {
                return;
            }
            var needRetry = command.NeedRetry;

            using (var scope = IoCFactory.Instance.CurrentContainer.CreateChildContainer())
            {
                scope.RegisterInstance(typeof(IMessageContext), commandContext);
                var eventMessageStates = new List <MessageState>();
                var messageStore       = scope.Resolve <IMessageStore>();
                var eventBus           = scope.Resolve <IEventBus>();
                var commandHasHandled  = messageStore.HasCommandHandled(commandContext.MessageID);
                if (commandHasHandled)
                {
                    if (needReply)
                    {
                        messageReply = _messageQueueClient.WrapMessage(new MessageDuplicatelyHandled(), commandContext.MessageID, commandContext.ReplyToEndPoint);
                        eventMessageStates.Add(new MessageState(messageReply));
                    }
                }
                else
                {
                    var messageHandlerType = _handlerProvider.GetHandlerTypes(command.GetType()).FirstOrDefault();
                    _logger.InfoFormat("Handle command, commandID:{0}", commandContext.MessageID);

                    if (messageHandlerType == null)
                    {
                        if (needReply)
                        {
                            messageReply = _messageQueueClient.WrapMessage(new NoHandlerExists(), commandContext.MessageID, commandContext.ReplyToEndPoint);
                            eventMessageStates.Add(new MessageState(messageReply));
                        }
                    }
                    else
                    {
                        object messageHandler = null;
                        do
                        {
                            try
                            {
                                if (messageHandler == null)
                                {
                                    messageHandler = scope.Resolve(messageHandlerType.Type);
                                }

                                using (var transactionScope = new TransactionScope(TransactionScopeOption.Required,
                                                                                   new TransactionOptions {
                                    IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted
                                },
                                                                                   TransactionScopeAsyncFlowOption.Enabled))
                                {
                                    if (messageHandlerType.IsAsync)
                                    {
                                        await((dynamic)messageHandler).Handle((dynamic)command)
                                        .ConfigureAwait(false);
                                    }
                                    else
                                    {
                                        await Task.Run(() =>
                                        {
                                            ((dynamic)messageHandler).Handle((dynamic)command);
                                        }).ConfigureAwait(false);
                                    }
                                    if (needReply)
                                    {
                                        messageReply = _messageQueueClient.WrapMessage(commandContext.Reply, commandContext.MessageID, commandContext.ReplyToEndPoint);
                                        eventMessageStates.Add(new MessageState(messageReply));
                                    }

                                    eventBus.GetEvents().ForEach(@event =>
                                    {
                                        var topic = @event.GetTopic();
                                        if (!string.IsNullOrEmpty(topic))
                                        {
                                            topic = Configuration.Instance.FormatAppName(topic);
                                        }
                                        var eventContext = _messageQueueClient.WrapMessage(@event, commandContext.MessageID, topic, @event.Key, sagaInfo: sagaInfo);
                                        eventMessageStates.Add(new MessageState(eventContext));
                                    });

                                    eventBus.GetToPublishAnywayMessages().ForEach(@event =>
                                    {
                                        var topic = @event.GetTopic();
                                        if (!string.IsNullOrEmpty(topic))
                                        {
                                            topic = Configuration.Instance.FormatAppName(topic);
                                        }
                                        var eventContext = _messageQueueClient.WrapMessage(@event, commandContext.MessageID, topic, @event.Key, sagaInfo: sagaInfo);
                                        eventMessageStates.Add(new MessageState(eventContext));
                                    });

                                    messageStore.SaveCommand(commandContext, eventMessageStates.Select(s => s.MessageContext).ToArray());
                                    transactionScope.Complete();
                                }
                                needRetry = false;
                            }
                            catch (Exception e)
                            {
                                eventMessageStates.Clear();
                                if (e is OptimisticConcurrencyException && needRetry)
                                {
                                    eventBus.ClearMessages();
                                }
                                else
                                {
                                    messageStore.Rollback();
                                    if (needReply)
                                    {
                                        messageReply = _messageQueueClient.WrapMessage(e.GetBaseException(), commandContext.MessageID, commandContext.ReplyToEndPoint);
                                        eventMessageStates.Add(new MessageState(messageReply));
                                    }
                                    eventBus.GetToPublishAnywayMessages().ForEach(@event =>
                                    {
                                        var topic = @event.GetTopic();
                                        if (!string.IsNullOrEmpty(topic))
                                        {
                                            topic = Configuration.Instance.FormatAppName(topic);
                                        }
                                        var eventContext = _messageQueueClient.WrapMessage(@event, commandContext.MessageID, topic, @event.Key, sagaInfo: sagaInfo);
                                        eventMessageStates.Add(new MessageState(eventContext));
                                    });

                                    if (e is DomainException)
                                    {
                                        _logger.Warn(command.ToJson(), e);
                                    }
                                    else
                                    {
                                        _logger.Error(command.ToJson(), e);
                                    }
                                    messageStore.SaveFailedCommand(commandContext, e, eventMessageStates.Select(s => s.MessageContext).ToArray());
                                    needRetry = false;
                                }
                            }
                        } while (needRetry);
                    }
                }
                try
                {
                    if (_messagePublisher != null && eventMessageStates.Count > 0)
                    {
                        _messagePublisher.SendAsync(eventMessageStates.ToArray());
                    }
                }
                catch (Exception ex)
                {
                    _logger.Error($"_messagePublisher SendAsync error", ex);
                }
                _removeMessageContext(commandContext);
            }
        }
コード例 #4
0
        protected async Task ConsumeMessage(IMessageContext eventContext)
        {
            var message             = eventContext.Message;
            var sagaInfo            = eventContext.SagaInfo;
            var messageHandlerTypes = _handlerProvider.GetHandlerTypes(message.GetType());

            if (messageHandlerTypes.Count == 0)
            {
                _removeMessageContext(eventContext);
                return;
            }

            SaveEvent(eventContext);
            //messageHandlerTypes.ForEach(messageHandlerType =>
            foreach (var messageHandlerType in messageHandlerTypes)
            {
                using (var scope = IoCFactory.Instance.CurrentContainer.CreateChildContainer())
                {
                    scope.RegisterInstance(typeof(IMessageContext), eventContext);
                    var messageStore     = scope.Resolve <IMessageStore>();
                    var subscriptionName = string.Format("{0}.{1}", _subscriptionName, messageHandlerType.Type.FullName);
                    if (!messageStore.HasEventHandled(eventContext.MessageID, subscriptionName))
                    {
                        var eventMessageStates   = new List <MessageState>();
                        var commandMessageStates = new List <MessageState>();
                        var eventBus             = scope.Resolve <IEventBus>();
                        try
                        {
                            var messageHandler = scope.Resolve(messageHandlerType.Type);
                            using (var transactionScope = new TransactionScope(TransactionScopeOption.Required,
                                                                               new TransactionOptions
                            {
                                IsolationLevel = IsolationLevel.ReadUncommitted
                            },
                                                                               TransactionScopeAsyncFlowOption.Enabled))
                            {
                                if (messageHandlerType.IsAsync)
                                {
                                    await((dynamic)messageHandler).Handle((dynamic)message)
                                    .ConfigureAwait(false);
                                }
                                else
                                {
                                    await Task.Run(() =>
                                    {
                                        ((dynamic)messageHandler).Handle((dynamic)message);
                                    }).ConfigureAwait(false);
                                }

                                //get commands to be sent
                                eventBus.GetCommands().ForEach(cmd =>
                                                               commandMessageStates.Add(new MessageState(_commandBus?.WrapCommand(cmd, sagaInfo: sagaInfo)))
                                                               );
                                //get events to be published
                                eventBus.GetEvents().ForEach(msg =>
                                {
                                    var topic = msg.GetTopic();
                                    if (!string.IsNullOrEmpty(topic))
                                    {
                                        topic = Configuration.Instance.FormatAppName(topic);
                                    }
                                    eventMessageStates.Add(new MessageState(_MessageQueueClient.WrapMessage(msg, topic: topic, key: msg.Key, sagaInfo: sagaInfo)));
                                });

                                eventBus.GetToPublishAnywayMessages().ForEach(msg =>
                                {
                                    var topic = msg.GetTopic();
                                    if (!string.IsNullOrEmpty(topic))
                                    {
                                        topic = Configuration.Instance.FormatAppName(topic);
                                    }
                                    eventMessageStates.Add(new MessageState(_MessageQueueClient.WrapMessage(msg, topic: topic, key: msg.Key, sagaInfo: sagaInfo)));
                                });

                                if (sagaInfo != null)
                                {
                                    eventBus.GetSagaResults().ForEach(sagaResult =>
                                    {
                                        var topic = sagaInfo.ReplyEndPoint;
                                        if (!string.IsNullOrEmpty(topic))
                                        {
                                            var sagaReply = _MessageQueueClient.WrapMessage(sagaResult,
                                                                                            topic: topic,
                                                                                            messageId: ObjectId.GenerateNewId().ToString(),
                                                                                            sagaInfo: sagaInfo);
                                            eventMessageStates.Add(new MessageState(sagaReply));
                                        }
                                    });
                                }
                                messageStore.HandleEvent(eventContext,
                                                         subscriptionName,
                                                         commandMessageStates.Select(s => s.MessageContext),
                                                         eventMessageStates.Select(s => s.MessageContext));

                                transactionScope.Complete();
                            }
                            if (commandMessageStates.Count > 0)
                            {
                                _commandBus?.SendMessageStates(commandMessageStates);
                            }
                            if (eventMessageStates.Count > 0)
                            {
                                _messagePublisher?.SendAsync(eventMessageStates.ToArray());
                            }
                        }
                        catch (Exception e)
                        {
                            if (e is DomainException)
                            {
                                _logger.Warn(message.ToJson(), e);
                            }
                            else
                            {
                                //IO error or sytem Crash
                                _logger.Error(message.ToJson(), e);
                            }
                            messageStore.Rollback();
                            eventBus.GetToPublishAnywayMessages().ForEach(msg =>
                            {
                                var topic = msg.GetTopic();
                                if (!string.IsNullOrEmpty(topic))
                                {
                                    topic = Configuration.Instance.FormatAppName(topic);
                                }
                                eventMessageStates.Add(new MessageState(_MessageQueueClient.WrapMessage(msg, topic: topic, key: msg.Key, sagaInfo: sagaInfo)));
                            });
                            messageStore.SaveFailHandledEvent(eventContext, subscriptionName, e, eventMessageStates.Select(s => s.MessageContext).ToArray());
                            if (eventMessageStates.Count > 0)
                            {
                                _messagePublisher?.SendAsync(eventMessageStates.ToArray());
                            }
                        }
                    }
                }
            }
            _removeMessageContext(eventContext);
        }
コード例 #5
0
        protected virtual async Task ConsumeMessage(IMessageContext commandContext)
        {
            Stopwatch watch = Stopwatch.StartNew();

            try
            {
                var command   = commandContext.Message as ICommand;
                var needReply = !string.IsNullOrEmpty(commandContext.ReplyToEndPoint);
                var sagaInfo  = commandContext.SagaInfo;
                if (command == null)
                {
                    InternalConsumer.CommitOffset(commandContext);
                    return;
                }

                var needRetry = command.NeedRetry;

                using (var scope = ObjectProviderFactory.Instance
                                   .ObjectProvider
                                   .CreateScope(builder => builder.RegisterInstance(typeof(IMessageContext), commandContext)))
                {
                    using (Logger.BeginScope(new
                    {
                        commandContext.Topic,
                        commandContext.MessageId,
                        commandContext.Key
                    }))
                    {
                        var messageStore       = scope.GetService <IMessageStore>();
                        var eventMessageStates = new List <MessageState>();
                        var commandHandledInfo = await messageStore.GetCommandHandledInfoAsync(commandContext.MessageId)
                                                 .ConfigureAwait(false);

                        IMessageContext messageReply = null;
                        if (commandHandledInfo != null)
                        {
                            if (needReply)
                            {
                                messageReply = MessageQueueClient.WrapMessage(commandHandledInfo.Result,
                                                                              commandContext.MessageId,
                                                                              commandContext.ReplyToEndPoint, producer: Producer,
                                                                              messageId: ObjectId.GenerateNewId().ToString());
                                eventMessageStates.Add(new MessageState(messageReply));
                            }
                        }
                        else
                        {
                            var eventBus           = scope.GetService <IEventBus>();
                            var messageHandlerType = HandlerProvider.GetHandlerTypes(command.GetType()).FirstOrDefault();
                            Logger.LogInformation("Handle command, commandID:{0}", commandContext.MessageId);

                            if (messageHandlerType == null)
                            {
                                Logger.LogDebug($"command has no handlerTypes, message:{command.ToJson()}");
                                if (needReply)
                                {
                                    messageReply = MessageQueueClient.WrapMessage(new NoHandlerExists(),
                                                                                  commandContext.MessageId,
                                                                                  commandContext.ReplyToEndPoint, producer: Producer);
                                    eventMessageStates.Add(new MessageState(messageReply));
                                }
                            }
                            else
                            {
                                object messageHandler = null;
                                do
                                {
                                    try
                                    {
                                        if (messageHandler == null)
                                        {
                                            messageHandler = scope.GetRequiredService(messageHandlerType.Type);
                                        }

                                        using (var transactionScope = new TransactionScope(TransactionScopeOption.Required,
                                                                                           new TransactionOptions {
                                            IsolationLevel = IsolationLevel.ReadCommitted
                                        },
                                                                                           TransactionScopeAsyncFlowOption.Enabled))
                                        {
                                            if (messageHandlerType.IsAsync)
                                            {
                                                await((dynamic)messageHandler).Handle((dynamic)command)
                                                .ConfigureAwait(false);
                                            }
                                            else
                                            {
                                                var handler = messageHandler;
                                                await Task.Run(() => { ((dynamic)handler).Handle((dynamic)command); }).ConfigureAwait(false);
                                            }

                                            if (needReply)
                                            {
                                                messageReply = MessageQueueClient.WrapMessage(commandContext.Reply,
                                                                                              commandContext.MessageId,
                                                                                              commandContext.ReplyToEndPoint,
                                                                                              producer: Producer);
                                                eventMessageStates.Add(new MessageState(messageReply));
                                            }

                                            eventBus.GetEvents()
                                            .ForEach(@event =>
                                            {
                                                var topic        = @event.GetFormatTopic();
                                                var eventContext = MessageQueueClient.WrapMessage(@event,
                                                                                                  commandContext.MessageId,
                                                                                                  topic,
                                                                                                  @event.Key,
                                                                                                  sagaInfo: sagaInfo,
                                                                                                  producer: Producer);
                                                eventMessageStates.Add(new MessageState(eventContext));
                                            });

                                            eventBus.GetToPublishAnywayMessages()
                                            .ForEach(@event =>
                                            {
                                                var topic        = @event.GetFormatTopic();
                                                var eventContext = MessageQueueClient.WrapMessage(@event,
                                                                                                  commandContext.MessageId,
                                                                                                  topic,
                                                                                                  @event.Key,
                                                                                                  sagaInfo: sagaInfo,
                                                                                                  producer: Producer);
                                                eventMessageStates.Add(new MessageState(eventContext));
                                            });

                                            eventMessageStates.AddRange(GetSagaReplyMessageStates(sagaInfo, eventBus));

                                            await messageStore.SaveCommandAsync(commandContext, commandContext.Reply,
                                                                                eventMessageStates.Select(s => s.MessageContext).ToArray())
                                            .ConfigureAwait(false);

                                            transactionScope.Complete();
                                        }

                                        needRetry = false;
                                    }
                                    catch (Exception e)
                                    {
                                        eventMessageStates.Clear();
                                        messageStore.Rollback();

                                        if (e is DBConcurrencyException && needRetry)
                                        {
                                            eventBus.ClearMessages();
                                        }
                                        else
                                        {
                                            if (needReply)
                                            {
                                                messageReply = MessageQueueClient.WrapMessage(e,
                                                                                              commandContext.MessageId,
                                                                                              commandContext.ReplyToEndPoint,
                                                                                              producer: Producer,
                                                                                              messageId: ObjectId.GenerateNewId().ToString());
                                                eventMessageStates.Add(new MessageState(messageReply));
                                            }

                                            eventBus.GetToPublishAnywayMessages()
                                            .ForEach(@event =>
                                            {
                                                var topic        = @event.GetFormatTopic();
                                                var eventContext = MessageQueueClient.WrapMessage(@event,
                                                                                                  commandContext.MessageId,
                                                                                                  topic,
                                                                                                  @event.Key,
                                                                                                  sagaInfo: sagaInfo,
                                                                                                  producer: Producer);
                                                eventMessageStates.Add(new MessageState(eventContext));
                                            });
                                            if (e is DomainException exception)
                                            {
                                                var domainExceptionEvent = exception.DomainExceptionEvent;
                                                if (domainExceptionEvent != null)
                                                {
                                                    var topic = domainExceptionEvent.GetFormatTopic();

                                                    var exceptionMessage = MessageQueueClient.WrapMessage(domainExceptionEvent,
                                                                                                          commandContext.MessageId,
                                                                                                          topic,
                                                                                                          producer: Producer);
                                                    eventMessageStates.Add(new MessageState(exceptionMessage));
                                                }

                                                Logger.LogWarning(e, command.ToJson());
                                            }
                                            else
                                            {
                                                Logger.LogError(e, command.ToJson());
                                                //if we meet with unknown exception, we interrupt saga
                                                if (sagaInfo != null)
                                                {
                                                    eventBus.FinishSaga(e);
                                                }
                                            }

                                            eventMessageStates.AddRange(GetSagaReplyMessageStates(sagaInfo, eventBus));
                                            await messageStore.SaveFailedCommandAsync(commandContext, e,
                                                                                      eventMessageStates.Select(s => s.MessageContext)
                                                                                      .ToArray())
                                            .ConfigureAwait(false);

                                            needRetry = false;
                                        }
                                    }
                                } while (needRetry);
                            }
                        }

                        if (eventMessageStates.Count > 0)
                        {
                            var sendTask = MessagePublisher.SendAsync(CancellationToken.None,
                                                                      eventMessageStates.ToArray());
                            // we don't need to wait the send task complete here.
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.LogCritical(ex, $"{ConsumerId} CommandProcessor consume command failed");
            }
            finally
            {
                watch.Stop();
                Logger.LogDebug($"{commandContext.ToJson()} consumed cost:{watch.ElapsedMilliseconds}ms");
            }

            InternalConsumer.CommitOffset(commandContext);
        }
コード例 #6
0
        protected virtual async Task ConsumeMessage(IMessageContext commandContext)
        {
            try
            {
                var             command      = commandContext.Message as ICommand;
                var             needReply    = !string.IsNullOrEmpty(commandContext.ReplyToEndPoint);
                var             sagaInfo     = commandContext.SagaInfo;
                IMessageContext messageReply = null;
                if (command == null)
                {
                    _internalConsumer.CommitOffset(commandContext);
                    return;
                }
                var needRetry = command.NeedRetry;

                using (var scope = IoCFactory.Instance.CurrentContainer.CreateChildContainer())
                {
                    scope.RegisterInstance(typeof(IMessageContext), commandContext);
                    var messageStore       = scope.Resolve <IMessageStore>();
                    var eventMessageStates = new List <MessageState>();
                    var commandHandledInfo = messageStore.GetCommandHandledInfo(commandContext.MessageID);
                    if (commandHandledInfo != null)
                    {
                        if (needReply)
                        {
                            messageReply = _messageQueueClient.WrapMessage(commandHandledInfo.Result,
                                                                           commandContext.MessageID,
                                                                           commandContext.ReplyToEndPoint, producer: Producer,
                                                                           messageId: ObjectId.GenerateNewId().ToString());
                            eventMessageStates.Add(new MessageState(messageReply));
                        }
                    }
                    else
                    {
                        var eventBus           = scope.Resolve <IEventBus>();
                        var messageHandlerType = _handlerProvider.GetHandlerTypes(command.GetType()).FirstOrDefault();
                        _logger?.InfoFormat("Handle command, commandID:{0}", commandContext.MessageID);

                        if (messageHandlerType == null)
                        {
                            _logger?.Debug($"command has no handlerTypes, message:{command.ToJson()}");
                            if (needReply)
                            {
                                messageReply = _messageQueueClient.WrapMessage(new NoHandlerExists(),
                                                                               commandContext.MessageID,
                                                                               commandContext.ReplyToEndPoint, producer: Producer);
                                eventMessageStates.Add(new MessageState(messageReply));
                            }
                        }
                        else
                        {
                            object messageHandler = null;
                            do
                            {
                                try
                                {
                                    if (messageHandler == null)
                                    {
                                        messageHandler = scope.Resolve(messageHandlerType.Type);
                                    }

                                    using (var transactionScope = new TransactionScope(TransactionScopeOption.Required,
                                                                                       new TransactionOptions {
                                        IsolationLevel = IsolationLevel.ReadCommitted
                                    },
                                                                                       TransactionScopeAsyncFlowOption.Enabled))
                                    {
                                        if (messageHandlerType.IsAsync)
                                        {
                                            await((dynamic)messageHandler).Handle((dynamic)command)
                                            .ConfigureAwait(false);
                                        }
                                        else
                                        {
                                            var handler = messageHandler;
                                            await Task.Run(() => { ((dynamic)handler).Handle((dynamic)command); }).ConfigureAwait(false);
                                        }
                                        if (needReply)
                                        {
                                            messageReply = _messageQueueClient.WrapMessage(commandContext.Reply,
                                                                                           commandContext.MessageID, commandContext.ReplyToEndPoint,
                                                                                           producer: Producer);
                                            eventMessageStates.Add(new MessageState(messageReply));
                                        }

                                        eventBus.GetEvents()
                                        .ForEach(@event =>
                                        {
                                            var topic        = @event.GetFormatTopic();
                                            var eventContext = _messageQueueClient.WrapMessage(@event,
                                                                                               commandContext.MessageID, topic, @event.Key,
                                                                                               sagaInfo: sagaInfo, producer: Producer);
                                            eventMessageStates.Add(new MessageState(eventContext));
                                        });

                                        eventBus.GetToPublishAnywayMessages()
                                        .ForEach(@event =>
                                        {
                                            var topic        = @event.GetFormatTopic();
                                            var eventContext = _messageQueueClient.WrapMessage(@event,
                                                                                               commandContext.MessageID, topic,
                                                                                               @event.Key, sagaInfo: sagaInfo, producer: Producer);
                                            eventMessageStates.Add(new MessageState(eventContext));
                                        });

                                        eventMessageStates.AddRange(GetSagaReplyMessageStates(sagaInfo, eventBus));

                                        messageStore.SaveCommand(commandContext, commandContext.Reply,
                                                                 eventMessageStates.Select(s => s.MessageContext).ToArray());
                                        transactionScope.Complete();
                                    }
                                    needRetry = false;
                                }
                                catch (Exception e)
                                {
                                    eventMessageStates.Clear();
                                    messageStore.Rollback();

                                    if (e is OptimisticConcurrencyException && needRetry)
                                    {
                                        eventBus.ClearMessages();
                                    }
                                    else
                                    {
                                        if (needReply)
                                        {
                                            messageReply = _messageQueueClient.WrapMessage(e.GetBaseException(),
                                                                                           commandContext.MessageID,
                                                                                           commandContext.ReplyToEndPoint,
                                                                                           producer: Producer,
                                                                                           messageId: ObjectId.GenerateNewId().ToString());
                                            eventMessageStates.Add(new MessageState(messageReply));
                                        }
                                        eventBus.GetToPublishAnywayMessages()
                                        .ForEach(@event =>
                                        {
                                            var topic        = @event.GetFormatTopic();
                                            var eventContext = _messageQueueClient.WrapMessage(@event,
                                                                                               commandContext.MessageID,
                                                                                               topic, @event.Key, sagaInfo: sagaInfo, producer: Producer);
                                            eventMessageStates.Add(new MessageState(eventContext));
                                        });
                                        if (e is DomainException exception)
                                        {
                                            var domainExceptionEvent = exception.DomainExceptionEvent;
                                            if (domainExceptionEvent != null)
                                            {
                                                var topic = domainExceptionEvent.GetFormatTopic();

                                                var exceptionMessage = _messageQueueClient.WrapMessage(domainExceptionEvent,
                                                                                                       commandContext.MessageID,
                                                                                                       topic,
                                                                                                       producer: Producer);
                                                eventMessageStates.Add(new MessageState(exceptionMessage));
                                            }
                                            _logger?.Warn(command.ToJson(), e);
                                        }
                                        else
                                        {
                                            _logger?.Error(command.ToJson(), e);
                                            //if we meet with unknown exception, we interrupt saga
                                            if (sagaInfo != null)
                                            {
                                                eventBus.FinishSaga(e);
                                            }
                                        }
                                        eventMessageStates.AddRange(GetSagaReplyMessageStates(sagaInfo, eventBus));
                                        messageStore.SaveFailedCommand(commandContext, e,
                                                                       eventMessageStates.Select(s => s.MessageContext).ToArray());
                                        needRetry = false;
                                    }
                                }
                            } while (needRetry);
                        }
                    }
                    if (eventMessageStates.Count > 0)
                    {
                        var sendTask = _messagePublisher.SendAsync(eventMessageStates.ToArray());
                        // we don't need to wait the send task complete here.
                    }
                }
            }
            catch (Exception ex)
            {
                _logger?.Fatal($"consume command failed", ex);
            }
            _internalConsumer.CommitOffset(commandContext);
        }
コード例 #7
0
        protected void ConsumeMessage(IMessageContext eventContext)
        {
            var message             = eventContext.Message;
            var messageHandlerTypes = _handlerProvider.GetHandlerTypes(message.GetType());

            if (messageHandlerTypes.Count == 0)
            {
                return;
            }

            messageHandlerTypes.ForEach(messageHandlerType =>
            {
                PerMessageContextLifetimeManager.CurrentMessageContext = eventContext;
                eventContext.ToBeSentMessageContexts.Clear();
                var messageStore     = IoCFactory.Resolve <IMessageStore>();
                var subscriptionName = string.Format("{0}.{1}", _subscriptionName, messageHandlerType.FullName);
                if (!messageStore.HasEventHandled(eventContext.MessageID, subscriptionName))
                {
                    bool success        = false;
                    var messageContexts = new List <IMessageContext>();
                    List <IMessageContext> commandContexts = null;
                    try
                    {
                        var messageHandler = IoCFactory.Resolve(messageHandlerType);
                        using (var transactionScope = new TransactionScope(TransactionScopeOption.Required,
                                                                           new TransactionOptions {
                            IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted
                        }))
                        {
                            ((dynamic)messageHandler).Handle((dynamic)message);

                            //get commands to be sent
                            commandContexts = eventContext.ToBeSentMessageContexts;
                            //get events to be published
                            var eventBus = IoCFactory.Resolve <IEventBus>();
                            eventBus.GetMessages().ForEach(msg => messageContexts.Add(_MessageQueueClient.WrapMessage(msg)));

                            messageStore.SaveEvent(eventContext, subscriptionName, commandContexts, messageContexts);
                            transactionScope.Complete();
                        }
                        success = true;
                    }
                    catch (Exception e)
                    {
                        if (e is DomainException)
                        {
                            _logger.Warn(message.ToJson(), e);
                        }
                        else
                        {
                            //IO error or sytem Crash
                            _logger.Error(message.ToJson(), e);
                        }
                        messageStore.SaveFailHandledEvent(eventContext, subscriptionName, e);
                    }
                    if (success)
                    {
                        if (commandContexts.Count > 0)
                        {
                            _commandBus.Send(commandContexts.AsEnumerable());
                        }
                        if (messageContexts.Count > 0)
                        {
                            _messagePublisher.Send(messageContexts.ToArray());
                        }
                    }
                }
                PerMessageContextLifetimeManager.CurrentMessageContext = null;
            });
        }
コード例 #8
0
        protected async Task ConsumeMessage(IMessageContext eventContext)
        {
            try
            {
                Logger.LogDebug($"start handle event {ConsumerId} {eventContext.Message.ToJson()}");

                var message = eventContext.Message;
                if (message == null)
                {
                    Logger.LogDebug($"message is null! messageContext: {eventContext.ToJson()}");
                    return;
                }

                var sagaInfo            = eventContext.SagaInfo;
                var messageHandlerTypes = HandlerProvider.GetHandlerTypes(message.GetType());

                if (messageHandlerTypes.Count == 0)
                {
                    Logger.LogDebug($"event has no handlerTypes, messageType:{message.GetType()} message:{message.ToJson()}");
                    return;
                }

                //messageHandlerTypes.ForEach(messageHandlerType =>
                foreach (var messageHandlerType in messageHandlerTypes)
                {
                    using (var scope = ObjectProviderFactory.Instance
                                       .ObjectProvider
                                       .CreateScope(builder => builder.RegisterInstance(typeof(IMessageContext), eventContext)))
                    {
                        var messageStore     = scope.GetService <IMessageStore>();
                        var subscriptionName = $"{SubscriptionName}.{messageHandlerType.Type.FullName}";
                        using (Logger.BeginScope(new
                        {
                            eventContext.Topic,
                            eventContext.MessageId,
                            eventContext.Key,
                            subscriptionName
                        }))
                        {
                            var eventMessageStates   = new List <MessageState>();
                            var commandMessageStates = new List <MessageState>();
                            var eventBus             = scope.GetService <IEventBus>();
                            try
                            {
                                if (!await messageStore.HasEventHandledAsync(eventContext.MessageId,
                                                                             subscriptionName)
                                    .ConfigureAwait(false))
                                {
                                    var messageHandler = scope.GetRequiredService(messageHandlerType.Type);
                                    using (var transactionScope = new TransactionScope(TransactionScopeOption.Required,
                                                                                       new TransactionOptions
                                    {
                                        IsolationLevel = IsolationLevel.ReadCommitted
                                    },
                                                                                       TransactionScopeAsyncFlowOption.Enabled))
                                    {
                                        if (messageHandlerType.IsAsync)
                                        {
                                            await((dynamic)messageHandler).Handle((dynamic)message)
                                            .ConfigureAwait(false);
                                        }
                                        else
                                        {
                                            ((dynamic)messageHandler).Handle((dynamic)message);
                                        }

                                        //get commands to be sent
                                        eventBus.GetCommands()
                                        .ForEach(cmd =>
                                                 commandMessageStates.Add(new MessageState(CommandBus?.WrapCommand(cmd,
                                                                                                                   sagaInfo: sagaInfo, producer: Producer)))
                                                 );
                                        //get events to be published
                                        eventBus.GetEvents()
                                        .ForEach(msg =>
                                        {
                                            var topic = msg.GetFormatTopic();
                                            eventMessageStates.Add(new MessageState(MessageQueueClient.WrapMessage(msg,
                                                                                                                   topic: topic,
                                                                                                                   key: msg.Key, sagaInfo: sagaInfo, producer: Producer)));
                                        });

                                        eventBus.GetToPublishAnywayMessages()
                                        .ForEach(msg =>
                                        {
                                            var topic = msg.GetFormatTopic();
                                            eventMessageStates.Add(new MessageState(MessageQueueClient.WrapMessage(msg,
                                                                                                                   topic: topic, key: msg.Key,
                                                                                                                   sagaInfo: sagaInfo, producer: Producer)));
                                        });

                                        eventMessageStates.AddRange(GetSagaReplyMessageStates(sagaInfo, eventBus));

                                        await messageStore.HandleEventAsync(eventContext,
                                                                            subscriptionName,
                                                                            commandMessageStates.Select(s => s.MessageContext),
                                                                            eventMessageStates.Select(s => s.MessageContext))
                                        .ConfigureAwait(false);

                                        transactionScope.Complete();
                                    }

                                    if (commandMessageStates.Count > 0)
                                    {
                                        CommandBus?.SendMessageStates(commandMessageStates);
                                    }

                                    if (eventMessageStates.Count > 0)
                                    {
                                        MessagePublisher?.SendAsync(CancellationToken.None, eventMessageStates.ToArray());
                                    }
                                }
                            }
                            catch (Exception e)
                            {
                                eventMessageStates.Clear();
                                messageStore.Rollback();
                                if (e is DomainException exception)
                                {
                                    var domainExceptionEvent = exception.DomainExceptionEvent;
                                    if (domainExceptionEvent != null)
                                    {
                                        var topic            = domainExceptionEvent.GetFormatTopic();
                                        var exceptionMessage = MessageQueueClient.WrapMessage(domainExceptionEvent,
                                                                                              eventContext.MessageId,
                                                                                              topic,
                                                                                              producer: Producer);
                                        eventMessageStates.Add(new MessageState(exceptionMessage));
                                    }

                                    Logger.LogWarning(e, message.ToJson());
                                }
                                else
                                {
                                    //IO error or sytem Crash
                                    //if we meet with unknown exception, we interrupt saga
                                    if (sagaInfo != null)
                                    {
                                        eventBus.FinishSaga(e);
                                    }

                                    Logger.LogError(e, message.ToJson());
                                }

                                eventBus.GetToPublishAnywayMessages()
                                .ForEach(msg =>
                                {
                                    var topic = msg.GetFormatTopic();
                                    eventMessageStates.Add(new MessageState(MessageQueueClient.WrapMessage(msg,
                                                                                                           topic: topic,
                                                                                                           key: msg.Key,
                                                                                                           sagaInfo: sagaInfo,
                                                                                                           producer: Producer)));
                                });

                                eventMessageStates.AddRange(GetSagaReplyMessageStates(sagaInfo, eventBus));

                                await messageStore.SaveFailHandledEventAsync(eventContext, subscriptionName, e,
                                                                             eventMessageStates.Select(s => s.MessageContext).ToArray())
                                .ConfigureAwait(false);

                                if (eventMessageStates.Count > 0)
                                {
                                    var sendTask = MessagePublisher.SendAsync(CancellationToken.None, eventMessageStates.ToArray());
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Logger.LogCritical(e, $"Handle event failed event: {eventContext.ToJson()}");
            }
            finally
            {
                InternalConsumer.CommitOffset(eventContext);
            }
        }