public void EnqueueMessage(ProcessingDomainEventStreamMessage message)
        {
            lock (_lockObj)
            {
                var eventStream = message.Message;
                if (eventStream.Version == LatestHandledEventVersion + 1)
                {
                    message.MailBox = this;
                    _messageQueue.Enqueue(message);
                    _logger.DebugFormat("{0} enqueued new message, aggregateRootType: {1}, aggregateRootId: {2}, commandId: {3}, eventVersion: {4}, eventStreamId: {5}, eventTypes: {6}, eventIds: {7}",
                                        GetType().Name,
                                        eventStream.AggregateRootTypeName,
                                        eventStream.AggregateRootId,
                                        eventStream.CommandId,
                                        eventStream.Version,
                                        eventStream.Id,
                                        string.Join("|", eventStream.Events.Select(x => x.GetType().Name)),
                                        string.Join("|", eventStream.Events.Select(x => x.Id))
                                        );
                    LatestHandledEventVersion = eventStream.Version;

                    var nextVersion = eventStream.Version + 1;
                    while (_waitingMessageDict.TryRemove(nextVersion, out ProcessingDomainEventStreamMessage nextMessage))
                    {
                        var nextEventStream = nextMessage.Message;
                        nextMessage.MailBox = this;
                        _messageQueue.Enqueue(nextMessage);
                        LatestHandledEventVersion = nextEventStream.Version;
                        _logger.DebugFormat("{0} enqueued new message, aggregateRootType: {1}, aggregateRootId: {2}, commandId: {3}, eventVersion: {4}, eventStreamId: {5}, eventTypes: {6}, eventIds: {7}",
                                            GetType().Name,
                                            eventStream.AggregateRootTypeName,
                                            nextEventStream.AggregateRootId,
                                            nextEventStream.CommandId,
                                            nextEventStream.Version,
                                            nextEventStream.Id,
                                            string.Join("|", eventStream.Events.Select(x => x.GetType().Name)),
                                            string.Join("|", nextEventStream.Events.Select(x => x.Id))
                                            );
                        nextVersion++;
                    }

                    LastActiveTime = DateTime.Now;
                    TryRun();
                }
                else if (eventStream.Version > LatestHandledEventVersion + 1)
                {
                    _waitingMessageDict.TryAdd(eventStream.Version, message);
                }
            }
        }
 private void DispatchProcessingMessageAsync(ProcessingDomainEventStreamMessage processingMessage, int retryTimes)
 {
     _ioHelper.TryAsyncActionRecursively("DispatchProcessingMessageAsync",
                                         () => _dispatcher.DispatchMessagesAsync(processingMessage.Message.Events),
                                         currentRetryTimes => DispatchProcessingMessageAsync(processingMessage, currentRetryTimes),
                                         result =>
     {
         UpdatePublishedVersionAsync(processingMessage, 0);
     },
                                         () => string.Format("sequence message [messageId:{0}, messageType:{1}, aggregateRootId:{2}, aggregateRootVersion:{3}]", processingMessage.Message.Id, processingMessage.Message.GetType().Name, processingMessage.Message.AggregateRootId, processingMessage.Message.Version),
                                         errorMessage =>
     {
         _logger.Fatal(string.Format("Dispatching message has unknown exception, the code should not be run to here, errorMessage: {0}", errorMessage));
     },
                                         retryTimes, true);
 }
        private void UpdatePublishedVersionAsync(ProcessingDomainEventStreamMessage processingMessage, int retryTimes)
        {
            var message = processingMessage.Message;

            _ioHelper.TryAsyncActionRecursively("UpdatePublishedVersionAsync",
                                                () => _publishedVersionStore.UpdatePublishedVersionAsync(_processorName, message.AggregateRootTypeName, message.AggregateRootId, message.Version),
                                                currentRetryTimes => UpdatePublishedVersionAsync(processingMessage, currentRetryTimes),
                                                result =>
            {
                processingMessage.Complete();
            },
                                                () => string.Format("DomainEventStreamMessage [messageId:{0}, messageType:{1}, aggregateRootId:{2}, aggregateRootVersion:{3}]", message.Id, message.GetType().Name, message.AggregateRootId, message.Version),
                                                errorMessage =>
            {
                _logger.Fatal(string.Format("Update published version has unknown exception, the code should not be run to here, errorMessage: {0}", errorMessage));
            },
                                                retryTimes, true);
        }
        public void Process(ProcessingDomainEventStreamMessage processingMessage)
        {
            var aggregateRootId = processingMessage.Message.AggregateRootId;

            if (string.IsNullOrEmpty(aggregateRootId))
            {
                throw new ArgumentException("aggregateRootId of domain event stream cannot be null or empty, domainEventStreamId:" + processingMessage.Message.Id);
            }

            lock (_lockObj)
            {
                var mailbox = _mailboxDict.GetOrAdd(aggregateRootId, x =>
                {
                    var latestHandledEventVersion = GetAggregateRootLatestHandledEventVersion(processingMessage.Message.AggregateRootTypeName, aggregateRootId);
                    return(new ProcessingDomainEventStreamMessageMailBox(aggregateRootId, latestHandledEventVersion, y => DispatchProcessingMessageAsync(y, 0), _logger));
                });
                mailbox.EnqueueMessage(processingMessage);
            }
        }