コード例 #1
0
 private void CommitEventAsync(EventCommittingContext context, int retryTimes)
 {
     _ioHelper.TryAsyncActionRecursively <AsyncTaskResult <EventAppendResult> >("PersistEventAsync",
                                                                                () => _eventStore.AppendAsync(context.EventStream),
                                                                                currentRetryTimes => CommitEventAsync(context, currentRetryTimes),
                                                                                result =>
     {
         if (result.Data == EventAppendResult.Success)
         {
             if (_logger.IsDebugEnabled)
             {
                 _logger.DebugFormat("Persist events success, {0}", context.EventStream);
             }
             RefreshAggregateMemoryCache(context);
             PublishDomainEventAsync(context.ProcessingCommand, context.EventStream);
         }
         else if (result.Data == EventAppendResult.DuplicateEvent)
         {
             HandleDuplicateEventResult(context);
         }
         else if (result.Data == EventAppendResult.DuplicateCommand)
         {
             HandleDuplicateCommandResult(context, 0);
         }
     },
                                                                                () => string.Format("[eventStream:{0}]", context.EventStream),
                                                                                errorMessage => context.ProcessingCommand.Complete(new CommandResult(CommandStatus.Failed, context.ProcessingCommand.Message.Id, context.EventStream.AggregateRootId, errorMessage ?? "Persist event async failed.", typeof(string).FullName)),
                                                                                retryTimes);
 }
コード例 #2
0
        private void HandleDuplicateCommandResult(EventCommittingContext context, int retryTimes)
        {
            var command = context.ProcessingCommand.Message;

            _ioHelper.TryAsyncActionRecursively <AsyncTaskResult <DomainEventStream> >("FindEventStreamByCommandIdAsync",
                                                                                       () => _eventStore.FindAsync(command.AggregateRootId, command.Id),
                                                                                       currentRetryTimes => HandleDuplicateCommandResult(context, currentRetryTimes),
                                                                                       result =>
            {
                var existingEventStream = result.Data;
                if (existingEventStream != null)
                {
                    //这里,我们需要再重新做一遍更新内存缓存以及发布事件这两个操作;
                    //之所以要这样做是因为虽然该command产生的事件已经持久化成功,但并不表示已经内存也更新了或者事件已经发布出去了;
                    //因为有可能事件持久化成功了,但那时正好机器断电了,则更新内存和发布事件都没有做;
                    RefreshAggregateMemoryCache(existingEventStream);
                    PublishDomainEventAsync(context.ProcessingCommand, existingEventStream);
                }
                else
                {
                    //到这里,说明当前command想添加到eventStore中时,提示command重复,但是尝试从eventStore中取出该command时却找不到该command。
                    //出现这种情况,我们就无法再做后续处理了,这种错误理论上不会出现,除非eventStore的Add接口和Get接口出现读写不一致的情况;
                    //我们记录错误日志,然后认为当前command已被处理为失败。
                    var errorMessage = string.Format("Command exist in the event store, but we cannot get it from the event store. commandType:{0}, commandId:{1}, aggregateRootId:{2}",
                                                     command.GetType().Name,
                                                     command.Id,
                                                     command.AggregateRootId);
                    _logger.Error(errorMessage);
                    context.ProcessingCommand.Complete(new CommandResult(CommandStatus.Failed, command.Id, command.AggregateRootId, "Duplicate command execution.", typeof(string).FullName));
                }
            },
                                                                                       () => string.Format("[aggregateRootId:{0}, commandId:{1}]", command.AggregateRootId, command.Id),
                                                                                       errorMessage => context.ProcessingCommand.Complete(new CommandResult(CommandStatus.Failed, command.Id, command.AggregateRootId, "Find event stream by commandId failed.", typeof(string).FullName)),
                                                                                       retryTimes);
        }
コード例 #3
0
        public void CommitDomainEventAsync(EventCommittingContext context)
        {
            var eventMailbox = _eventMailboxDict.GetOrAdd(context.AggregateRoot.UniqueId, x =>
            {
                return(new EventMailBox(x, _batchSize, committingContexts =>
                {
                    if (committingContexts == null || committingContexts.Count == 0)
                    {
                        return;
                    }
                    if (_eventStore.SupportBatchAppendEvent)
                    {
                        BatchPersistEventAsync(committingContexts, 0);
                    }
                    else
                    {
                        PersistEventOneByOne(committingContexts);
                    }
                }));
            });

            eventMailbox.EnqueueMessage(context);
            RefreshAggregateMemoryCache(context);
            context.ProcessingCommand.Mailbox.TryExecuteNextMessage();
        }
コード例 #4
0
        private async Task ResetCommandMailBoxConsumingSequence(EventCommittingContext context, long consumingSequence)
        {
            var processingCommand = context.ProcessingCommand;
            var command           = processingCommand.Message;
            var commandMailBox    = processingCommand.MailBox;
            var eventMailBox      = context.MailBox;
            var aggregateRootId   = context.EventStream.AggregateRootId;

            commandMailBox.Pause();

            try
            {
                eventMailBox.RemoveAggregateAllEventCommittingContexts(aggregateRootId);
                var refreshedAggregateRoot = await _memoryCache.RefreshAggregateFromEventStoreAsync(context.EventStream.AggregateRootTypeName, aggregateRootId);

                commandMailBox.ResetConsumingSequence(consumingSequence);
            }
            catch (Exception ex)
            {
                _logger.Error(string.Format("ResetCommandMailBoxConsumingSequence has unknown exception, aggregateRootId: {0}", command.AggregateRootId), ex);
            }
            finally
            {
                commandMailBox.Resume();
                commandMailBox.TryRun();
                eventMailBox.CompleteRun();
            }
        }
コード例 #5
0
        private async Task ResetCommandMailBoxConsumingSequence(EventCommittingContext context, long consumingSequence)
        {
            var eventMailBox      = context.MailBox;
            var processingCommand = context.ProcessingCommand;
            var command           = processingCommand.Message;
            var commandMailBox    = processingCommand.MailBox;

            commandMailBox.Pause();
            try
            {
                await RefreshAggregateMemoryCacheToLatestVersion(context.EventStream.AggregateRootTypeName, context.EventStream.AggregateRootId);

                commandMailBox.ResetConsumingSequence(consumingSequence);
                eventMailBox.Clear();
                eventMailBox.Exit();
                _logger.InfoFormat("ResetCommandMailBoxConsumingSequence success, commandId: {0}, aggregateRootId: {1}, consumingSequence: {2}", command.Id, command.AggregateRootId, consumingSequence);
            }
            catch (Exception ex)
            {
                _logger.Error(string.Format("ResetCommandMailBoxConsumingOffset has unknown exception, commandId: {0}, aggregateRootId: {1}", command.Id, command.AggregateRootId), ex);
            }
            finally
            {
                commandMailBox.Resume();
            }
        }
コード例 #6
0
        private void TryToRepublishEventAsync(EventCommittingContext context, int retryTimes)
        {
            var command = context.ProcessingCommand.Message;

            _ioHelper.TryAsyncActionRecursively("FindEventByCommandIdAsync",
                                                () => _eventStore.FindAsync(command.AggregateRootId, command.Id),
                                                currentRetryTimes => TryToRepublishEventAsync(context, currentRetryTimes),
                                                result =>
            {
                var existingEventStream = result.Data;
                if (existingEventStream != null)
                {
                    //这里,我们需要再重新做一遍发布事件这个操作;
                    //之所以要这样做是因为虽然该command产生的事件已经持久化成功,但并不表示事件已经发布出去了;
                    //因为有可能事件持久化成功了,但那时正好机器断电了,则发布事件都没有做;
                    PublishDomainEventAsync(context.ProcessingCommand, existingEventStream);
                }
                else
                {
                    //到这里,说明当前command想添加到eventStore中时,提示command重复,但是尝试从eventStore中取出该command时却找不到该command。
                    //出现这种情况,我们就无法再做后续处理了,这种错误理论上不会出现,除非eventStore的Add接口和Get接口出现读写不一致的情况;
                    //框架会记录错误日志,让开发者排查具体是什么问题。
                    var errorMessage = string.Format("Command should be exist in the event store, but we cannot find it from the event store, this should not be happen, and we cannot continue again. commandType:{0}, commandId:{1}, aggregateRootId:{2}",
                                                     command.GetType().Name,
                                                     command.Id,
                                                     command.AggregateRootId);
                    _logger.Fatal(errorMessage);
                    var commandResult = new CommandResult(CommandStatus.Failed, command.Id, command.AggregateRootId, "Command should be exist in the event store, but we cannot find it from the event store.", typeof(string).FullName);
                    CompleteCommand(context.ProcessingCommand, commandResult);
                }
            },
                                                () => string.Format("[aggregateRootId:{0}, commandId:{1}]", command.AggregateRootId, command.Id),
                                                null,
                                                retryTimes, true);
        }
コード例 #7
0
        private async Task ResetCommandMailBoxConsumingSequence(EventCommittingContext context, long consumingSequence, IList <string> duplicateCommandIdList)
        {
            var commandMailBox  = context.ProcessingCommand.MailBox;
            var eventMailBox    = context.MailBox;
            var aggregateRootId = context.EventStream.AggregateRootId;

            commandMailBox.Pause();

            try
            {
                eventMailBox.RemoveAggregateAllEventCommittingContexts(aggregateRootId);
                var refreshedAggregateRoot = await _memoryCache.RefreshAggregateFromEventStoreAsync(context.EventStream.AggregateRootTypeName, aggregateRootId).ConfigureAwait(false);

                if (duplicateCommandIdList != null)
                {
                    foreach (var commandId in duplicateCommandIdList)
                    {
                        commandMailBox.AddDuplicateCommandId(commandId);
                    }
                }
                commandMailBox.ResetConsumingSequence(consumingSequence);
            }
            catch (Exception ex)
            {
                _logger.Error(string.Format("ResetCommandMailBoxConsumingSequence has unknown exception, aggregateRootId: {0}", aggregateRootId), ex);
            }
            finally
            {
                commandMailBox.Resume();
                commandMailBox.TryRun();
            }
        }
コード例 #8
0
        public void CommitDomainEventAsync(EventCommittingContext eventCommittingContext)
        {
            var eventMailboxIndex = GetEventMailBoxIndex(eventCommittingContext.EventStream.AggregateRootId);
            var eventMailbox      = _eventCommittingContextMailBoxList[eventMailboxIndex];

            eventMailbox.EnqueueMessage(eventCommittingContext);
        }
コード例 #9
0
        private void HandleFirstEventDuplicationAsync(EventCommittingContext context, int retryTimes)
        {
            var eventStream = context.EventStream;

            _ioHelper.TryAsyncActionRecursively("FindFirstEventByVersion",
                                                () => _eventStore.FindAsync(eventStream.AggregateRootId, 1),
                                                currentRetryTimes => HandleFirstEventDuplicationAsync(context, currentRetryTimes),
                                                result =>
            {
                var firstEventStream = result.Data;
                if (firstEventStream != null)
                {
                    //判断是否是同一个command,如果是,则再重新做一遍发布事件;
                    //之所以要这样做,是因为虽然该command产生的事件已经持久化成功,但并不表示事件也已经发布出去了;
                    //有可能事件持久化成功了,但那时正好机器断电了,则发布事件都没有做;
                    if (context.ProcessingCommand.Message.Id == firstEventStream.CommandId)
                    {
                        ResetCommandMailBoxConsumingSequence(context, context.ProcessingCommand.Sequence + 1).ContinueWith(t =>
                        {
                            PublishDomainEventAsync(context.ProcessingCommand, firstEventStream);
                        }).ConfigureAwait(false);
                    }
                    else
                    {
                        //如果不是同一个command,则认为是两个不同的command重复创建ID相同的聚合根,我们需要记录错误日志,然后通知当前command的处理完成;
                        var errorMessage = string.Format("Duplicate aggregate creation. current commandId:{0}, existing commandId:{1}, aggregateRootId:{2}, aggregateRootTypeName:{3}",
                                                         context.ProcessingCommand.Message.Id,
                                                         firstEventStream.CommandId,
                                                         firstEventStream.AggregateRootId,
                                                         firstEventStream.AggregateRootTypeName);
                        _logger.Error(errorMessage);
                        ResetCommandMailBoxConsumingSequence(context, context.ProcessingCommand.Sequence + 1).ContinueWith(t =>
                        {
                            var commandResult = new CommandResult(CommandStatus.Failed, context.ProcessingCommand.Message.Id, eventStream.AggregateRootId, "Duplicate aggregate creation.", typeof(string).FullName);
                            CompleteCommand(context.ProcessingCommand, commandResult);
                        }).ConfigureAwait(false);
                    }
                }
                else
                {
                    var errorMessage = string.Format("Duplicate aggregate creation, but we cannot find the existing eventstream from eventstore, this should not be happen, and we cannot continue again. commandId:{0}, aggregateRootId:{1}, aggregateRootTypeName:{2}",
                                                     eventStream.CommandId,
                                                     eventStream.AggregateRootId,
                                                     eventStream.AggregateRootTypeName);
                    _logger.Fatal(errorMessage);
                    ResetCommandMailBoxConsumingSequence(context, context.ProcessingCommand.Sequence + 1).ContinueWith(t =>
                    {
                        var commandResult = new CommandResult(CommandStatus.Failed, context.ProcessingCommand.Message.Id, eventStream.AggregateRootId, "Duplicate aggregate creation, but we cannot find the existing eventstream from eventstore.", typeof(string).FullName);
                        CompleteCommand(context.ProcessingCommand, commandResult);
                    }).ConfigureAwait(false);
                }
            },
                                                () => string.Format("[eventStream:{0}]", eventStream),
                                                errorMessage =>
            {
                _logger.Fatal(string.Format("Find the first version of event has unknown exception, the code should not be run to here, errorMessage: {0}", errorMessage));
            },
                                                retryTimes, true);
        }
コード例 #10
0
ファイル: DefaultEventService.cs プロジェクト: bes-slim/enode
        private void RetryConcurrentCommand(EventCommittingContext context)
        {
            var processingCommand = context.ProcessingCommand;
            var command           = processingCommand.Message;

            processingCommand.IncreaseConcurrentRetriedCount();
            processingCommand.CommandExecuteContext.Clear();
            _logger.InfoFormat("Begin to retry command as it meets the concurrent conflict. commandType:{0}, commandId:{1}, aggregateRootId:{2}, retried count:{3}.", command.GetType().Name, command.Id, processingCommand.Message.AggregateRootId, processingCommand.ConcurrentRetriedCount);
            _processingCommandHandler.HandleAsync(processingCommand);
        }
コード例 #11
0
        private void PersistEventAsync(EventCommittingContext context, int retryTimes)
        {
            _ioHelper.TryAsyncActionRecursively("PersistEventAsync",
                                                () => _eventStore.AppendAsync(context.EventStream),
                                                currentRetryTimes => PersistEventAsync(context, currentRetryTimes),
                                                result =>
            {
                if (result.Data == EventAppendResult.Success)
                {
                    if (_logger.IsDebugEnabled)
                    {
                        _logger.DebugFormat("Persist event success, {0}", context.EventStream);
                    }

                    Task.Factory.StartNew(x =>
                    {
                        var currentContext = x as EventCommittingContext;
                        PublishDomainEventAsync(currentContext.ProcessingCommand, currentContext.EventStream);
                    }, context);

                    if (context.Next != null)
                    {
                        PersistEventAsync(context.Next, 0);
                    }
                    else
                    {
                        context.MailBox.TryRun(true);
                    }
                }
                else if (result.Data == EventAppendResult.DuplicateEvent)
                {
                    if (context.EventStream.Version == 1)
                    {
                        HandleFirstEventDuplicationAsync(context, 0);
                    }
                    else
                    {
                        _logger.WarnFormat("Persist event has concurrent version conflict, eventStream: {0}", context.EventStream);
                        ResetCommandMailBoxConsumingSequence(context, context.ProcessingCommand.Sequence).ContinueWith(t => { }).ConfigureAwait(false);
                    }
                }
                else if (result.Data == EventAppendResult.DuplicateCommand)
                {
                    _logger.WarnFormat("Persist event has duplicate command, eventStream: {0}", context.EventStream);
                    ResetCommandMailBoxConsumingSequence(context, context.ProcessingCommand.Sequence + 1).ContinueWith(t => { }).ConfigureAwait(false);
                    TryToRepublishEventAsync(context, 0);
                }
            },
                                                () => string.Format("[eventStream:{0}]", context.EventStream),
                                                errorMessage =>
            {
                _logger.Fatal(string.Format("Persist event has unknown exception, the code should not be run to here, errorMessage: {0}", errorMessage));
            },
                                                retryTimes, true);
        }
コード例 #12
0
 private void ProcessDuplicateEvent(EventCommittingContext eventCommittingContext)
 {
     if (eventCommittingContext.EventStream.Version == 1)
     {
         HandleFirstEventDuplicationAsync(eventCommittingContext, 0);
     }
     else
     {
         ResetCommandMailBoxConsumingSequence(eventCommittingContext, eventCommittingContext.ProcessingCommand.Sequence).ContinueWith(t => { }).ConfigureAwait(false);
     }
 }
コード例 #13
0
        private Task HandleFirstEventDuplicationAsync(EventCommittingContext context, int retryTimes)
        {
            var taskCompletionSource = new TaskCompletionSource <bool>();

            _ioHelper.TryAsyncActionRecursively("FindFirstEventByVersion",
                                                () => _eventStore.FindAsync(context.EventStream.AggregateRootId, 1),
                                                currentRetryTimes => HandleFirstEventDuplicationAsync(context, currentRetryTimes),
                                                async result =>
            {
                if (result != null)
                {
                    var eventStream = result;
                    //判断是否是同一个command,如果是,则再重新做一遍发布事件;
                    //之所以要这样做,是因为虽然该command产生的事件已经持久化成功,但并不表示事件也已经发布出去了;
                    //有可能事件持久化成功了,但那时正好机器断电了,则发布事件都没有做;
                    if (context.ProcessingCommand.Message.Id == eventStream.CommandId)
                    {
                        await ResetCommandMailBoxConsumingSequence(context, context.ProcessingCommand.Sequence + 1, null).ConfigureAwait(false);
                        PublishDomainEventAsync(context.ProcessingCommand, eventStream);
                    }
                    else
                    {
                        //如果不是同一个command,则认为是两个不同的command重复创建ID相同的聚合根,我们需要记录错误日志,然后通知当前command的处理完成;
                        var errorMessage = string.Format("Duplicate aggregate creation. current commandId:{0}, existing commandId:{1}, aggregateRootId:{2}, aggregateRootTypeName:{3}",
                                                         context.ProcessingCommand.Message.Id,
                                                         eventStream.CommandId,
                                                         eventStream.AggregateRootId,
                                                         eventStream.AggregateRootTypeName);
                        _logger.Error(errorMessage);
                        await ResetCommandMailBoxConsumingSequence(context, context.ProcessingCommand.Sequence + 1, null).ConfigureAwait(false);
                        var commandResult = new CommandResult(CommandStatus.Failed, context.ProcessingCommand.Message.Id, context.EventStream.AggregateRootId, "Duplicate aggregate creation.", typeof(string).FullName);
                        await CompleteCommand(context.ProcessingCommand, commandResult);
                    }
                }
                else
                {
                    var errorMessage = string.Format("Duplicate aggregate creation, but we cannot find the existing eventstream from eventstore, this should not be happen, and we cannot continue again. commandId:{0}, aggregateRootId:{1}, aggregateRootTypeName:{2}",
                                                     context.EventStream.CommandId,
                                                     context.EventStream.AggregateRootId,
                                                     context.EventStream.AggregateRootTypeName);
                    _logger.Fatal(errorMessage);
                    await ResetCommandMailBoxConsumingSequence(context, context.ProcessingCommand.Sequence + 1, null).ConfigureAwait(false);
                    var commandResult = new CommandResult(CommandStatus.Failed, context.ProcessingCommand.Message.Id, context.EventStream.AggregateRootId, "Duplicate aggregate creation, but we cannot find the existing eventstream from eventstore.", typeof(string).FullName);
                    await CompleteCommand(context.ProcessingCommand, commandResult);
                }

                taskCompletionSource.SetResult(true);
            },
                                                () => string.Format("[eventStream:{0}]", context.EventStream),
                                                null,
                                                retryTimes, true);

            return(taskCompletionSource.Task);
        }
コード例 #14
0
ファイル: DefaultEventService.cs プロジェクト: bes-slim/enode
 public void CommitDomainEventAsync(EventCommittingContext context)
 {
     if (_enableGroupCommit && _eventStore.SupportBatchAppend)
     {
         _toCommitContextQueue.Enqueue(context);
     }
     else
     {
         CommitEventAsync(context, 0);
     }
 }
コード例 #15
0
 private void TryProcessNextContext(EventCommittingContext currentContext)
 {
     if (currentContext.Next != null)
     {
         PersistEventAsync(currentContext.Next, 0);
     }
     else
     {
         currentContext.EventMailBox.RegisterForExecution(true);
     }
 }
コード例 #16
0
 private void RefreshAggregateMemoryCache(EventCommittingContext context)
 {
     try
     {
         context.AggregateRoot.AcceptChanges(context.EventStream.Version);
         _memoryCache.Set(context.AggregateRoot);
     }
     catch (Exception ex)
     {
         _logger.Error(string.Format("Refresh aggregate memory cache failed for event stream:{0}", context.EventStream), ex);
     }
 }
コード例 #17
0
ファイル: DefaultEventService.cs プロジェクト: bes-slim/enode
 private void RefreshAggregateMemoryCache(EventCommittingContext context)
 {
     try
     {
         context.AggregateRoot.AcceptChanges(context.EventStream.Version);
         _memoryCache.Set(context.AggregateRoot);
         _logger.DebugFormat("Refreshed aggregate memory cache, commandId:{0}, aggregateRootType:{1}, aggregateRootId:{2}, aggregateRootVersion:{3}", context.EventStream.CommandId, context.AggregateRoot.GetType().Name, context.AggregateRoot.UniqueId, context.AggregateRoot.Version);
     }
     catch (Exception ex)
     {
         _logger.Error(string.Format("Refresh memory cache failed by event stream:{0}", context.EventStream), ex);
     }
 }
コード例 #18
0
        private void ResetCommandMailBoxConsumingOffset(EventCommittingContext context, long consumeOffset)
        {
            var eventMailBox      = context.EventMailBox;
            var processingCommand = context.ProcessingCommand;
            var commandMailBox    = processingCommand.Mailbox;

            commandMailBox.StopHandlingMessage();
            UpdateAggregateMemoryCacheToLatestVersion(context.EventStream);
            commandMailBox.ResetConsumingOffset(consumeOffset);
            eventMailBox.Clear();
            eventMailBox.ExitHandlingMessage();
            commandMailBox.RestartHandlingMessage();
        }
コード例 #19
0
        private void PersistEventAsync(EventCommittingContext context, int retryTimes)
        {
            _ioHelper.TryAsyncActionRecursively("PersistEventAsync",
                                                () => _eventStore.AppendAsync(context.EventStream),
                                                currentRetryTimes => PersistEventAsync(context, currentRetryTimes),
                                                result =>
            {
                if (result.Data == EventAppendResult.Success)
                {
                    if (_logger.IsDebugEnabled)
                    {
                        _logger.DebugFormat("Persist event success, {0}", context.EventStream);
                    }

                    Task.Factory.StartNew(x =>
                    {
                        var currentContext = x as EventCommittingContext;
                        PublishDomainEventAsync(currentContext.ProcessingCommand, currentContext.EventStream);
                    }, context);

                    TryProcessNextContext(context);
                }
                else if (result.Data == EventAppendResult.DuplicateEvent)
                {
                    //如果是当前事件的版本号为1,则认为是在创建重复的聚合根
                    if (context.EventStream.Version == 1)
                    {
                        HandleFirstEventDuplicationAsync(context, 0);
                    }
                    //如果事件的版本大于1,则认为是更新聚合根时遇到并发冲突了,则需要进行重试;
                    else
                    {
                        _logger.WarnFormat("Persist event has concurrent version conflict, eventStream: {0}", context.EventStream);
                        ResetCommandMailBoxConsumingSequence(context, context.ProcessingCommand.Sequence);
                    }
                }
                else if (result.Data == EventAppendResult.DuplicateCommand)
                {
                    _logger.WarnFormat("Persist event has duplicate command, eventStream: {0}", context.EventStream);
                    ResetCommandMailBoxConsumingSequence(context, context.ProcessingCommand.Sequence + 1);
                    TryToRepublishEventAsync(context, 0);
                    context.EventMailBox.RegisterForExecution(true);
                }
            },
                                                () => string.Format("[eventStream:{0}]", context.EventStream),
                                                errorMessage =>
            {
                _logger.Fatal(string.Format("Persist event has unknown exception, the code should not be run to here, errorMessage: {0}", errorMessage));
            },
                                                retryTimes, true);
        }
コード例 #20
0
ファイル: DefaultEventService.cs プロジェクト: bes-slim/enode
 private void HandleDuplicateEventResult(EventCommittingContext context)
 {
     //如果是当前事件的版本号为1,则认为是在创建重复的聚合根
     if (context.EventStream.Version == 1)
     {
         HandleFirstEventDuplicationAsync(context, 0);
     }
     //如果事件的版本大于1,则认为是更新聚合根时遇到并发冲突了;
     //那么我们需要先将聚合根的最新状态更新到内存,然后重试command;
     else
     {
         UpdateAggregateToLatestVersion(context.EventStream.AggregateRootTypeCode, context.EventStream.AggregateRootId);
         RetryConcurrentCommand(context);
     }
 }
コード例 #21
0
ファイル: DefaultEventService.cs プロジェクト: bes-slim/enode
        private void HandleFirstEventDuplicationAsync(EventCommittingContext context, int retryTimes)
        {
            var eventStream = context.EventStream;

            _ioHelper.TryAsyncActionRecursively <AsyncTaskResult <DomainEventStream> >("FindFirstEventByVersion",
                                                                                       () => _eventStore.FindAsync(eventStream.AggregateRootId, 1),
                                                                                       currentRetryTimes => HandleFirstEventDuplicationAsync(context, currentRetryTimes),
                                                                                       result =>
            {
                var firstEventStream = result.Data;
                if (firstEventStream != null)
                {
                    //判断是否是同一个command,如果是,则再重新做一遍更新内存缓存以及发布事件这两个操作;
                    //之所以要这样做,是因为虽然该command产生的事件已经持久化成功,但并不表示已经内存也更新了或者事件已经发布出去了;
                    //有可能事件持久化成功了,但那时正好机器断电了,则更新内存和发布事件都没有做;
                    if (context.ProcessingCommand.Message.Id == firstEventStream.CommandId)
                    {
                        RefreshAggregateMemoryCache(firstEventStream);
                        PublishDomainEventAsync(context.ProcessingCommand, firstEventStream);
                    }
                    else
                    {
                        //如果不是同一个command,则认为是两个不同的command重复创建ID相同的聚合根,我们需要记录错误日志,然后通知当前command的处理完成;
                        var errorMessage = string.Format("Duplicate aggregate creation. current commandId:{0}, existing commandId:{1}, aggregateRootId:{2}, aggregateRootTypeCode:{3}",
                                                         context.ProcessingCommand.Message.Id,
                                                         eventStream.CommandId,
                                                         eventStream.AggregateRootId,
                                                         eventStream.AggregateRootTypeCode);
                        _logger.Error(errorMessage);
                        context.ProcessingCommand.Complete(new CommandResult(CommandStatus.Failed, context.ProcessingCommand.Message.Id, eventStream.AggregateRootId, null, "Duplicate aggregate creation."));
                    }
                }
                else
                {
                    var errorMessage = string.Format("Duplicate aggregate creation, but we cannot find the existing eventstream from eventstore. commandId:{0}, aggregateRootId:{1}, aggregateRootTypeCode:{2}",
                                                     eventStream.CommandId,
                                                     eventStream.AggregateRootId,
                                                     eventStream.AggregateRootTypeCode);
                    _logger.Error(errorMessage);
                    context.ProcessingCommand.Complete(new CommandResult(CommandStatus.Failed, context.ProcessingCommand.Message.Id, eventStream.AggregateRootId, null, "Duplicate aggregate creation, but we cannot find the existing eventstream from eventstore."));
                }
            },
                                                                                       () => string.Format("[eventStream:{0}]", eventStream),
                                                                                       () => context.ProcessingCommand.Complete(new CommandResult(CommandStatus.Failed, context.ProcessingCommand.Message.Id, eventStream.AggregateRootId, null, "Persist the first version of event duplicated, but try to get the first version of domain event async failed.")),
                                                                                       retryTimes);
        }
コード例 #22
0
        public void Run()
        {
            _lastActiveTime = DateTime.Now;
            IList <EventCommittingContext> contextList = null;

            try
            {
                EventCommittingContext context = null;
                while (_messageQueue.TryDequeue(out context))
                {
                    context.EventMailBox = this;
                    if (contextList == null)
                    {
                        contextList = new List <EventCommittingContext>();
                    }
                    contextList.Add(context);

                    if (contextList.Count == _batchSize)
                    {
                        break;
                    }
                }
                if (contextList != null && contextList.Count > 0)
                {
                    _handleMessageAction(contextList);
                }
            }
            catch (Exception ex)
            {
                _logger.Error(string.Format("Event mailbox run has unknown exception, aggregateRootId: {0}", AggregateRootId), ex);
                Thread.Sleep(1);
            }
            finally
            {
                if (contextList == null || contextList.Count == 0)
                {
                    Exit();
                    if (!_messageQueue.IsEmpty)
                    {
                        TryRun();
                    }
                }
            }
        }
コード例 #23
0
ファイル: EventMailBox.cs プロジェクト: zxh877027287/enode
        public void Run()
        {
            IList <EventCommittingContext> contextList = null;

            try
            {
                EventCommittingContext context = null;
                while (_messageQueue.TryDequeue(out context))
                {
                    context.EventMailBox = this;
                    if (contextList == null)
                    {
                        contextList = new List <EventCommittingContext>();
                    }
                    contextList.Add(context);

                    if (contextList.Count == _batchSize)
                    {
                        break;
                    }
                }
                if (contextList != null && contextList.Count > 0)
                {
                    _handleMessageAction(contextList);
                }
            }
            finally
            {
                if (contextList == null || contextList.Count == 0)
                {
                    ExitHandlingMessage();
                    if (!_messageQueue.IsEmpty)
                    {
                        RegisterForExecution();
                    }
                }
            }
        }
コード例 #24
0
        private void ResetCommandMailBoxConsumingSequence(EventCommittingContext context, long consumingSequence)
        {
            var eventMailBox      = context.EventMailBox;
            var processingCommand = context.ProcessingCommand;
            var commandMailBox    = processingCommand.Mailbox;

            commandMailBox.PauseHandlingMessage();
            try
            {
                UpdateAggregateMemoryCacheToLatestVersion(context.EventStream);
                commandMailBox.ResetConsumingSequence(consumingSequence);
                eventMailBox.Clear();
                eventMailBox.ExitHandlingMessage();
            }
            catch (Exception ex)
            {
                _logger.Error(string.Format("ResetCommandMailBoxConsumingOffset has unknown exception, commandId: {0}, aggregateRootId: {1}", processingCommand.Message.Id, processingCommand.Message.AggregateRootId), ex);
            }
            finally
            {
                commandMailBox.ResumeHandlingMessage();
            }
        }
コード例 #25
0
ファイル: DefaultEventService.cs プロジェクト: ulswww/enode
 public void CommitDomainEventAsync(EventCommittingContext context)
 {
     var eventMailbox = _eventMailboxDict.GetOrAdd(context.AggregateRoot.UniqueId, x =>
     {
         return new EventMailBox(x, _batchSize, committingContexts =>
         {
             if (committingContexts == null || committingContexts.Count == 0)
             {
                 return;
             }
             if (_eventStore.SupportBatchAppendEvent)
             {
                 BatchPersistEventAsync(committingContexts, 0);
             }
             else
             {
                 PersistEventOneByOne(committingContexts);
             }
         });
     });
     eventMailbox.EnqueueMessage(context);
     RefreshAggregateMemoryCache(context);
     context.ProcessingCommand.Mailbox.TryExecuteNextMessage();
 }
コード例 #26
0
 private void HandleDuplicateEventResult(EventCommittingContext context)
 {
     //如果是当前事件的版本号为1,则认为是在创建重复的聚合根
     if (context.EventStream.Version == 1)
     {
         HandleFirstEventDuplicationAsync(context, 0);
     }
     //如果事件的版本大于1,则认为是更新聚合根时遇到并发冲突了;
     //那么我们需要先将聚合根的最新状态更新到内存,然后重试command;
     else
     {
         UpdateAggregateToLatestVersion(context.EventStream.AggregateRootTypeName, context.EventStream.AggregateRootId);
         RetryConcurrentCommand(context);
     }
 }
コード例 #27
0
ファイル: DefaultEventService.cs プロジェクト: ulswww/enode
 private void TryProcessNextContext(EventCommittingContext currentContext)
 {
     if (currentContext.Next != null)
     {
         PersistEventAsync(currentContext.Next, 0);
     }
     else
     {
         currentContext.EventMailBox.RegisterForExecution(true);
     }
 }
コード例 #28
0
ファイル: EventMailBox.cs プロジェクト: ulswww/enode
 public void EnqueueMessage(EventCommittingContext message)
 {
     _messageQueue.Enqueue(message);
     RegisterForExecution();
 }
コード例 #29
0
ファイル: EventMailBox.cs プロジェクト: zxh877027287/enode
 public void EnqueueMessage(EventCommittingContext message)
 {
     _messageQueue.Enqueue(message);
     RegisterForExecution();
 }
コード例 #30
0
 public void CommitDomainEventAsync(EventCommittingContext context)
 {
     CommitEventAsync(context, 0);
 }
コード例 #31
0
ファイル: DefaultEventService.cs プロジェクト: ulswww/enode
        private void PersistEventAsync(EventCommittingContext context, int retryTimes)
        {
            _ioHelper.TryAsyncActionRecursively("PersistEventAsync",
            () => _eventStore.AppendAsync(context.EventStream),
            currentRetryTimes => PersistEventAsync(context, currentRetryTimes),
            result =>
            {
                if (result.Data == EventAppendResult.Success)
                {
                    if (_logger.IsDebugEnabled)
                    {
                        _logger.DebugFormat("Persist event success, {0}", context.EventStream);
                    }

                    Task.Factory.StartNew(x =>
                    {
                        var currentContext = x as EventCommittingContext;
                        PublishDomainEventAsync(currentContext.ProcessingCommand, currentContext.EventStream);
                    }, context);

                    TryProcessNextContext(context);
                }
                else if (result.Data == EventAppendResult.DuplicateEvent)
                {
                    //如果是当前事件的版本号为1,则认为是在创建重复的聚合根
                    if (context.EventStream.Version == 1)
                    {
                        HandleFirstEventDuplicationAsync(context, 0);
                    }
                    //如果事件的版本大于1,则认为是更新聚合根时遇到并发冲突了,则需要进行重试;
                    else
                    {
                        _logger.WarnFormat("Persist event has concurrent version conflict, eventStream: {0}", context.EventStream);
                        ResetCommandMailBoxConsumingOffset(context, context.ProcessingCommand.Sequence);
                    }
                }
                else if (result.Data == EventAppendResult.DuplicateCommand)
                {
                    _logger.WarnFormat("Persist event has duplicate command, eventStream: {0}", context.EventStream);
                    ResetCommandMailBoxConsumingOffset(context, context.ProcessingCommand.Sequence + 1);
                    TryToRepublishEventAsync(context, 0);
                    context.EventMailBox.RegisterForExecution(true);
                }
            },
            () => string.Format("[eventStream:{0}]", context.EventStream),
            errorMessage =>
            {
                _logger.Fatal(string.Format("Persist event has unknown exception, the code should not be run to here, errorMessage: {0}", errorMessage));
            },
            retryTimes, true);
        }
コード例 #32
0
ファイル: DefaultEventService.cs プロジェクト: ulswww/enode
 private void RefreshAggregateMemoryCache(EventCommittingContext context)
 {
     try
     {
         context.AggregateRoot.AcceptChanges(context.EventStream.Version);
         _memoryCache.Set(context.AggregateRoot);
     }
     catch (Exception ex)
     {
         _logger.Error(string.Format("Refresh memory cache failed for event stream:{0}", context.EventStream), ex);
     }
 }
コード例 #33
0
ファイル: DefaultEventService.cs プロジェクト: ulswww/enode
        private void ResetCommandMailBoxConsumingOffset(EventCommittingContext context, long consumeOffset)
        {
            var eventMailBox = context.EventMailBox;
            var processingCommand = context.ProcessingCommand;
            var commandMailBox = processingCommand.Mailbox;

            commandMailBox.StopHandlingMessage();
            UpdateAggregateMemoryCacheToLatestVersion(context.EventStream);
            commandMailBox.ResetConsumingOffset(consumeOffset);
            eventMailBox.Clear();
            eventMailBox.ExitHandlingMessage();
            commandMailBox.RestartHandlingMessage();
        }
コード例 #34
0
 private void CommitEventAsync(EventCommittingContext context, int retryTimes)
 {
     _ioHelper.TryAsyncActionRecursively<AsyncTaskResult<EventAppendResult>>("PersistEventAsync",
     () => _eventStore.AppendAsync(context.EventStream),
     currentRetryTimes => CommitEventAsync(context, currentRetryTimes),
     result =>
     {
         if (result.Data == EventAppendResult.Success)
         {
             if (_logger.IsDebugEnabled)
             {
                 _logger.DebugFormat("Persist events success, {0}", context.EventStream);
             }
             RefreshAggregateMemoryCache(context);
             PublishDomainEventAsync(context.ProcessingCommand, context.EventStream);
         }
         else if (result.Data == EventAppendResult.DuplicateEvent)
         {
             HandleDuplicateEventResult(context);
         }
         else if (result.Data == EventAppendResult.DuplicateCommand)
         {
             HandleDuplicateCommandResult(context, 0);
         }
     },
     () => string.Format("[eventStream:{0}]", context.EventStream),
     errorMessage => context.ProcessingCommand.Complete(new CommandResult(CommandStatus.Failed, context.ProcessingCommand.Message.Id, context.EventStream.AggregateRootId, errorMessage ?? "Persist event async failed.", typeof(string).FullName)),
     retryTimes);
 }
コード例 #35
0
ファイル: DefaultEventService.cs プロジェクト: ulswww/enode
        private void HandleFirstEventDuplicationAsync(EventCommittingContext context, int retryTimes)
        {
            var eventStream = context.EventStream;

            _ioHelper.TryAsyncActionRecursively("FindFirstEventByVersion",
            () => _eventStore.FindAsync(eventStream.AggregateRootId, 1),
            currentRetryTimes => HandleFirstEventDuplicationAsync(context, currentRetryTimes),
            result =>
            {
                var firstEventStream = result.Data;
                if (firstEventStream != null)
                {
                    //判断是否是同一个command,如果是,则再重新做一遍发布事件;
                    //之所以要这样做,是因为虽然该command产生的事件已经持久化成功,但并不表示事件也已经发布出去了;
                    //有可能事件持久化成功了,但那时正好机器断电了,则发布事件都没有做;
                    if (context.ProcessingCommand.Message.Id == firstEventStream.CommandId)
                    {
                        ResetCommandMailBoxConsumingOffset(context, context.ProcessingCommand.Sequence + 1);
                        PublishDomainEventAsync(context.ProcessingCommand, firstEventStream);
                    }
                    else
                    {
                        //如果不是同一个command,则认为是两个不同的command重复创建ID相同的聚合根,我们需要记录错误日志,然后通知当前command的处理完成;
                        var errorMessage = string.Format("Duplicate aggregate creation. current commandId:{0}, existing commandId:{1}, aggregateRootId:{2}, aggregateRootTypeName:{3}",
                            context.ProcessingCommand.Message.Id,
                            firstEventStream.CommandId,
                            firstEventStream.AggregateRootId,
                            firstEventStream.AggregateRootTypeName);
                        _logger.Error(errorMessage);
                        ResetCommandMailBoxConsumingOffset(context, context.ProcessingCommand.Sequence + 1);
                        CompleteCommand(context.ProcessingCommand, new CommandResult(CommandStatus.Failed, context.ProcessingCommand.Message.Id, eventStream.AggregateRootId, "Duplicate aggregate creation.", typeof(string).FullName));
                    }
                }
                else
                {
                    var errorMessage = string.Format("Duplicate aggregate creation, but we cannot find the existing eventstream from eventstore, this should not be happen, and we cannot continue again. commandId:{0}, aggregateRootId:{1}, aggregateRootTypeName:{2}",
                        eventStream.CommandId,
                        eventStream.AggregateRootId,
                        eventStream.AggregateRootTypeName);
                    _logger.Fatal(errorMessage);
                }
            },
            () => string.Format("[eventStream:{0}]", eventStream),
            errorMessage =>
            {
                _logger.Fatal(string.Format("Find the first version of event has unknown exception, the code should not be run to here, errorMessage: {0}", errorMessage));
            },
            retryTimes, true);
        }
コード例 #36
0
        private void HandleDuplicateCommandResult(EventCommittingContext context, int retryTimes)
        {
            var command = context.ProcessingCommand.Message;

            _ioHelper.TryAsyncActionRecursively<AsyncTaskResult<DomainEventStream>>("FindEventStreamByCommandIdAsync",
            () => _eventStore.FindAsync(command.AggregateRootId, command.Id),
            currentRetryTimes => HandleDuplicateCommandResult(context, currentRetryTimes),
            result =>
            {
                var existingEventStream = result.Data;
                if (existingEventStream != null)
                {
                    //这里,我们需要再重新做一遍更新内存缓存以及发布事件这两个操作;
                    //之所以要这样做是因为虽然该command产生的事件已经持久化成功,但并不表示已经内存也更新了或者事件已经发布出去了;
                    //因为有可能事件持久化成功了,但那时正好机器断电了,则更新内存和发布事件都没有做;
                    RefreshAggregateMemoryCache(existingEventStream);
                    PublishDomainEventAsync(context.ProcessingCommand, existingEventStream);
                }
                else
                {
                    //到这里,说明当前command想添加到eventStore中时,提示command重复,但是尝试从eventStore中取出该command时却找不到该command。
                    //出现这种情况,我们就无法再做后续处理了,这种错误理论上不会出现,除非eventStore的Add接口和Get接口出现读写不一致的情况;
                    //我们记录错误日志,然后认为当前command已被处理为失败。
                    var errorMessage = string.Format("Command exist in the event store, but we cannot get it from the event store. commandType:{0}, commandId:{1}, aggregateRootId:{2}",
                        command.GetType().Name,
                        command.Id,
                        command.AggregateRootId);
                    _logger.Error(errorMessage);
                    context.ProcessingCommand.Complete(new CommandResult(CommandStatus.Failed, command.Id, command.AggregateRootId, "Duplicate command execution.", typeof(string).FullName));
                }
            },
            () => string.Format("[aggregateRootId:{0}, commandId:{1}]", command.AggregateRootId, command.Id),
            errorMessage => context.ProcessingCommand.Complete(new CommandResult(CommandStatus.Failed, command.Id, command.AggregateRootId, "Find event stream by commandId failed.", typeof(string).FullName)),
            retryTimes);
        }
コード例 #37
0
 public void EnqueueMessage(EventCommittingContext message)
 {
     _messageQueue.Enqueue(message);
     _lastActiveTime = DateTime.Now;
     TryRun();
 }
コード例 #38
0
ファイル: DefaultEventService.cs プロジェクト: ulswww/enode
        private void TryToRepublishEventAsync(EventCommittingContext context, int retryTimes)
        {
            var command = context.ProcessingCommand.Message;

            _ioHelper.TryAsyncActionRecursively("FindEventByCommandIdAsync",
            () => _eventStore.FindAsync(command.AggregateRootId, command.Id),
            currentRetryTimes => TryToRepublishEventAsync(context, currentRetryTimes),
            result =>
            {
                var existingEventStream = result.Data;
                if (existingEventStream != null)
                {
                    //这里,我们需要再重新做一遍发布事件这个操作;
                    //之所以要这样做是因为虽然该command产生的事件已经持久化成功,但并不表示事件已经发布出去了;
                    //因为有可能事件持久化成功了,但那时正好机器断电了,则发布事件都没有做;
                    PublishDomainEventAsync(context.ProcessingCommand, existingEventStream);
                }
                else
                {
                    //到这里,说明当前command想添加到eventStore中时,提示command重复,但是尝试从eventStore中取出该command时却找不到该command。
                    //出现这种情况,我们就无法再做后续处理了,这种错误理论上不会出现,除非eventStore的Add接口和Get接口出现读写不一致的情况;
                    //框架会记录错误日志,让开发者排查具体是什么问题。
                    var errorMessage = string.Format("Command exist in the event store, but we cannot find it from the event store, this should not be happen, and we cannot continue again. commandType:{0}, commandId:{1}, aggregateRootId:{2}",
                        command.GetType().Name,
                        command.Id,
                        command.AggregateRootId);
                    _logger.Fatal(errorMessage);
                }
            },
            () => string.Format("[aggregateRootId:{0}, commandId:{1}]", command.AggregateRootId, command.Id),
            errorMessage =>
            {
                _logger.Fatal(string.Format("Find event by commandId has unknown exception, the code should not be run to here, errorMessage: {0}", errorMessage));
            },
            retryTimes, true);
        }
コード例 #39
0
 private void RefreshAggregateMemoryCache(EventCommittingContext context)
 {
     try
     {
         context.AggregateRoot.AcceptChanges(context.EventStream.Version);
         _memoryCache.Set(context.AggregateRoot);
         if (_logger.IsDebugEnabled)
         {
             _logger.DebugFormat("Refreshed aggregate memory cache, commandId:{0}, aggregateRootType:{1}, aggregateRootId:{2}, aggregateRootVersion:{3}", context.EventStream.CommandId, context.AggregateRoot.GetType().Name, context.AggregateRoot.UniqueId, context.AggregateRoot.Version);
         }
     }
     catch (Exception ex)
     {
         _logger.Error(string.Format("Refresh memory cache failed by event stream:{0}", context.EventStream), ex);
     }
 }
コード例 #40
0
 private void RetryConcurrentCommand(EventCommittingContext context)
 {
     var processingCommand = context.ProcessingCommand;
     var command = processingCommand.Message;
     processingCommand.IncreaseConcurrentRetriedCount();
     processingCommand.CommandExecuteContext.Clear();
     _logger.InfoFormat("Begin to retry command as it meets the concurrent conflict. commandType:{0}, commandId:{1}, aggregateRootId:{2}, retried count:{3}.", command.GetType().Name, command.Id, processingCommand.Message.AggregateRootId, processingCommand.ConcurrentRetriedCount);
     _processingCommandHandler.HandleAsync(processingCommand);
 }
コード例 #41
0
 public void CommitDomainEventAsync(EventCommittingContext context)
 {
     if (_enableGroupCommit && _eventStore.SupportBatchAppend)
     {
         _toCommitContextQueue.Enqueue(context);
     }
     else
     {
         CommitEventAsync(context, 0);
     }
 }
コード例 #42
0
        private void HandleFirstEventDuplicationAsync(EventCommittingContext context, int retryTimes)
        {
            var eventStream = context.EventStream;

            _ioHelper.TryAsyncActionRecursively<AsyncTaskResult<DomainEventStream>>("FindFirstEventByVersion",
            () => _eventStore.FindAsync(eventStream.AggregateRootId, 1),
            currentRetryTimes => HandleFirstEventDuplicationAsync(context, currentRetryTimes),
            result =>
            {
                var firstEventStream = result.Data;
                if (firstEventStream != null)
                {
                    //判断是否是同一个command,如果是,则再重新做一遍更新内存缓存以及发布事件这两个操作;
                    //之所以要这样做,是因为虽然该command产生的事件已经持久化成功,但并不表示已经内存也更新了或者事件已经发布出去了;
                    //有可能事件持久化成功了,但那时正好机器断电了,则更新内存和发布事件都没有做;
                    if (context.ProcessingCommand.Message.Id == firstEventStream.CommandId)
                    {
                        RefreshAggregateMemoryCache(firstEventStream);
                        PublishDomainEventAsync(context.ProcessingCommand, firstEventStream);
                    }
                    else
                    {
                        //如果不是同一个command,则认为是两个不同的command重复创建ID相同的聚合根,我们需要记录错误日志,然后通知当前command的处理完成;
                        var errorMessage = string.Format("Duplicate aggregate creation. current commandId:{0}, existing commandId:{1}, aggregateRootId:{2}, aggregateRootTypeName:{3}",
                            context.ProcessingCommand.Message.Id,
                            eventStream.CommandId,
                            eventStream.AggregateRootId,
                            eventStream.AggregateRootTypeName);
                        _logger.Error(errorMessage);
                        context.ProcessingCommand.Complete(new CommandResult(CommandStatus.Failed, context.ProcessingCommand.Message.Id, eventStream.AggregateRootId, "Duplicate aggregate creation.", typeof(string).FullName));
                    }
                }
                else
                {
                    var errorMessage = string.Format("Duplicate aggregate creation, but we cannot find the existing eventstream from eventstore. commandId:{0}, aggregateRootId:{1}, aggregateRootTypeName:{2}",
                        eventStream.CommandId,
                        eventStream.AggregateRootId,
                        eventStream.AggregateRootTypeName);
                    _logger.Error(errorMessage);
                    context.ProcessingCommand.Complete(new CommandResult(CommandStatus.Failed, context.ProcessingCommand.Message.Id, eventStream.AggregateRootId, "Duplicate aggregate creation, but we cannot find the existing eventstream from eventstore.", typeof(string).FullName));
                }
            },
            () => string.Format("[eventStream:{0}]", eventStream),
            errorMessage => context.ProcessingCommand.Complete(new CommandResult(CommandStatus.Failed, context.ProcessingCommand.Message.Id, eventStream.AggregateRootId, errorMessage ?? "Persist the first version of event duplicated, but try to get the first version of domain event async failed.", typeof(string).FullName)),
            retryTimes);
        }
コード例 #43
0
 public void CommitDomainEventAsync(EventCommittingContext context)
 {
     CommitEventAsync(context, 0);
 }