コード例 #1
0
        protected override void BeforeCommit()
        {
            base.BeforeCommit();
            _eventMessageStates.Clear();
            _eventBus.GetEvents()
            .ForEach(@event =>
            {
                var topic        = @event.GetFormatTopic();
                var eventContext = _messageQueueClient.WrapMessage(@event, null, topic, @event.Key);
                _eventMessageStates.Add(new MessageState(eventContext));
            });

            _eventBus.GetToPublishAnywayMessages()
            .ForEach(@event =>
            {
                var topic        = @event.GetFormatTopic();
                var eventContext = _messageQueueClient.WrapMessage(@event, null, topic, @event.Key);
                _anywayPublishEventMessageStates.Add(new MessageState(eventContext));
            });
            var allMessageStates = _eventMessageStates.Union(_anywayPublishEventMessageStates)
                                   .ToList();

            if (allMessageStates.Count > 0)
            {
                _messageStore.SaveCommand(null, null, allMessageStates.Select(s => s.MessageContext).ToArray());
            }
        }
コード例 #2
0
ファイル: UnitOfWork.cs プロジェクト: RaychZhang/IFramework
        protected override async Task BeforeCommitAsync()
        {
            await base.BeforeCommitAsync().ConfigureAwait(false);

            if (HasMessageContext)
            {
                return;
            }

            EventMessageStates.Clear();
            EventBus.GetEvents()
            .ForEach(@event =>
            {
                var topic        = @event.GetFormatTopic();
                var eventContext = MessageQueueClient.WrapMessage(@event, null, topic, @event.Key);
                EventMessageStates.Add(new MessageState(eventContext));
            });

            EventBus.GetToPublishAnywayMessages()
            .ForEach(@event =>
            {
                var topic        = @event.GetFormatTopic();
                var eventContext = MessageQueueClient.WrapMessage(@event, null, topic, @event.Key);
                AnywayPublishEventMessageStates.Add(new MessageState(eventContext));
            });
            var allMessageStates = EventMessageStates.Union(AnywayPublishEventMessageStates)
                                   .ToList();

            if (allMessageStates.Count > 0)
            {
                await MessageStore.SaveCommandAsync(null, null, allMessageStates.Select(s => s.MessageContext).ToArray())
                .ConfigureAwait(false);
            }
        }
コード例 #3
0
        private List <MessageState> GetSagaReplyMessageStates(SagaInfo sagaInfo, IEventBus eventBus)
        {
            var eventMessageStates = new List <MessageState>();

            if (sagaInfo != null && !string.IsNullOrWhiteSpace(sagaInfo.SagaId))
            {
                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, producer: Producer);
                        eventMessageStates.Add(new MessageState(sagaReply));
                    }
                });
            }
            return(eventMessageStates);
        }
コード例 #4
0
        public Task <MessageResponse[]> SendAsync(CancellationToken sendCancellationToken, params IMessage[] messages)
        {
            var sendTaskCompletionSource = new TaskCompletionSource <MessageResponse>();

            if (sendCancellationToken != CancellationToken.None)
            {
                sendCancellationToken.Register(OnSendCancel, sendTaskCompletionSource);
            }
            var messageStates = messages.Select(message =>
            {
                var topic = message.GetFormatTopic();
                return(new MessageState(_messageQueueClient.WrapMessage(message, topic: topic, key: message.Key),
                                        sendTaskCompletionSource,
                                        false));
            })
                                .ToArray();

            return(SendAsync(messageStates));
        }
コード例 #5
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);
        }
コード例 #6
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);
            }
        }
コード例 #7
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);
        }
コード例 #8
0
 public void Send(params IMessage[] messages)
 {
     messages.ForEach(message => _messageQueue.Add(_messageQueueClient.WrapMessage(message)));
 }
コード例 #9
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;
            });
        }
コード例 #10
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);
            }
        }
コード例 #11
0
        protected virtual void ConsumeMessage(IMessageContext commandContext)
        {
            var             command      = commandContext.Message as ICommand;
            IMessageContext messageReply = null;

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

            PerMessageContextLifetimeManager.CurrentMessageContext = commandContext;
            List <IMessageContext> eventContexts = new List <IMessageContext>();
            var messageStore      = IoCFactory.Resolve <IMessageStore>();
            var eventBus          = IoCFactory.Resolve <IEventBus>();
            var commandHasHandled = messageStore.HasCommandHandled(commandContext.MessageID);

            if (commandHasHandled)
            {
                messageReply = _messageQueueClient.WrapMessage(new MessageDuplicatelyHandled(), commandContext.MessageID, commandContext.ReplyToEndPoint);
                eventContexts.Add(messageReply);
            }
            else
            {
                var messageHandler = _handlerProvider.GetHandler(command.GetType());
                _logger.InfoFormat("Handle command, commandID:{0}", commandContext.MessageID);

                if (messageHandler == null)
                {
                    messageReply = _messageQueueClient.WrapMessage(new NoHandlerExists(), commandContext.MessageID, commandContext.ReplyToEndPoint);
                    eventContexts.Add(messageReply);
                }
                else
                {
                    do
                    {
                        try
                        {
                            using (var transactionScope = new TransactionScope(TransactionScopeOption.Required,
                                                                               new TransactionOptions {
                                IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted
                            }))
                            {
                                ((dynamic)messageHandler).Handle((dynamic)command);
                                messageReply = _messageQueueClient.WrapMessage(commandContext.Reply, commandContext.MessageID, commandContext.ReplyToEndPoint);
                                eventContexts.Add(messageReply);
                                eventBus.GetMessages().ForEach(@event => {
                                    var eventContext = _messageQueueClient.WrapMessage(@event, commandContext.MessageID);
                                    eventContexts.Add(eventContext);
                                });

                                messageStore.SaveCommand(commandContext, eventContexts.ToArray());
                                transactionScope.Complete();
                            }
                            needRetry = false;
                        }
                        catch (Exception e)
                        {
                            eventContexts.Clear();
                            if (e is OptimisticConcurrencyException && needRetry)
                            {
                                eventBus.ClearMessages();
                            }
                            else
                            {
                                messageReply = _messageQueueClient.WrapMessage(e.GetBaseException(), commandContext.MessageID, commandContext.ReplyToEndPoint);
                                eventContexts.Add(messageReply);
                                if (e is DomainException)
                                {
                                    _logger.Warn(command.ToJson(), e);
                                }
                                else
                                {
                                    _logger.Error(command.ToJson(), e);
                                }
                                messageStore.SaveFailedCommand(commandContext, e, messageReply);
                                needRetry = false;
                            }
                        }
                    } while (needRetry);
                }
            }
            if (_messagePublisher != null && eventContexts.Count > 0)
            {
                _messagePublisher.Send(eventContexts.ToArray());
            }
        }