コード例 #1
0
ファイル: DefaultEventService.cs プロジェクト: bes-slim/enode
 private void BatchPersistEventsAsync(IEnumerable <EventCommittingContext> contextList, int retryTimes)
 {
     _ioHelper.TryAsyncActionRecursively <AsyncTaskResult>("BatchPersistEventAsync",
                                                           () => _eventStore.BatchAppendAsync(contextList.Select(x => x.EventStream)),
                                                           currentRetryTimes => BatchPersistEventsAsync(contextList, currentRetryTimes),
                                                           result =>
     {
         _successPersistedContextQueue.Add(contextList);
         _logger.DebugFormat("Batch persist event stream success, persisted event stream count:{0}", contextList.Count());
         if (_toCommitContextQueue.Count >= _groupCommitMaxSize)
         {
             BatchPersistEventsAsync(DequeueContexts(), 0);
         }
         else
         {
             ExitBatchPersistingEvents();
         }
     },
                                                           () => string.Format("[contextListCount:{0}]", contextList.Count()),
                                                           () =>
     {
         _failedPersistedContextQueue.Add(contextList);
         ExitBatchPersistingEvents();
     },
                                                           retryTimes);
 }
コード例 #2
0
        private void BatchPersistEventAsync(IList <EventCommittingContext> committingContexts, int retryTimes)
        {
            _ioHelper.TryAsyncActionRecursively("BatchPersistEventAsync",
                                                () => _eventStore.BatchAppendAsync(committingContexts.Select(x => x.EventStream)),
                                                currentRetryTimes => BatchPersistEventAsync(committingContexts, currentRetryTimes),
                                                result =>
            {
                var eventMailBox = committingContexts.First().EventMailBox;
                var appendResult = result.Data;
                if (appendResult == EventAppendResult.Success)
                {
                    if (_logger.IsDebugEnabled)
                    {
                        _logger.DebugFormat("Batch persist event success, aggregateRootId: {0}, eventStreamCount: {1}", eventMailBox.AggregateRootId, committingContexts.Count);
                    }

                    Task.Factory.StartNew(x =>
                    {
                        var contextList = x as IList <EventCommittingContext>;
                        foreach (var context in contextList)
                        {
                            PublishDomainEventAsync(context.ProcessingCommand, context.EventStream);
                        }
                    }, committingContexts);

                    eventMailBox.RegisterForExecution(true);
                }
                else if (appendResult == EventAppendResult.DuplicateEvent)
                {
                    var context = committingContexts.First();
                    if (context.EventStream.Version == 1)
                    {
                        ConcatConetxts(committingContexts);
                        HandleFirstEventDuplicationAsync(context, 0);
                    }
                    else
                    {
                        _logger.WarnFormat("Batch persist event has concurrent version conflict, first eventStream: {0}, batchSize: {1}", context.EventStream, committingContexts.Count);
                        ResetCommandMailBoxConsumingSequence(context, context.ProcessingCommand.Sequence);
                    }
                }
                else if (appendResult == EventAppendResult.DuplicateCommand)
                {
                    PersistEventOneByOne(committingContexts);
                }
            },
                                                () => string.Format("[contextListCount:{0}]", committingContexts.Count),
                                                errorMessage =>
            {
                _logger.Fatal(string.Format("Batch persist event has unknown exception, the code should not be run to here, errorMessage: {0}", errorMessage));
            },
                                                retryTimes, true);
        }
コード例 #3
0
ファイル: DefaultEventService.cs プロジェクト: wandec/enode
        private void BatchPersistEventAsync(IList <EventCommittingContext> committingContexts, int retryTimes)
        {
            _ioHelper.TryAsyncActionRecursively("BatchPersistEventAsync",
                                                () => _eventStore.BatchAppendAsync(committingContexts.Select(x => x.EventStream)),
                                                currentRetryTimes => BatchPersistEventAsync(committingContexts, currentRetryTimes),
                                                result =>
            {
                var appendResult = result.Data;
                if (appendResult == EventAppendResult.Success)
                {
                    var eventMailBox = committingContexts.First().MailBox;
                    _logger.InfoFormat("Batch persist event success, routingKey: {0}, eventStreamCount: {1}, minEventVersion: {2}, maxEventVersion: {3}", eventMailBox.RoutingKey, committingContexts.Count, committingContexts.First().EventStream.Version, committingContexts.Last().EventStream.Version);

                    Task.Factory.StartNew(x =>
                    {
                        var contextList = x as IList <EventCommittingContext>;
                        foreach (var context in contextList)
                        {
                            PublishDomainEventAsync(context.ProcessingCommand, context.EventStream);
                        }
                    }, committingContexts);

                    foreach (var committingContext in committingContexts)
                    {
                        committingContext.MailBox.CompleteMessage(committingContext, true);
                    }

                    eventMailBox.CompleteRun();
                }
                else if (appendResult == EventAppendResult.DuplicateEvent)
                {
                    var eventMailBox = committingContexts.First().MailBox;
                    _logger.WarnFormat("Batch persist event has concurrent version conflict, routingKey: {0}, eventStreamCount: {1}, minEventVersion: {2}, maxEventVersion: {3}", eventMailBox.RoutingKey, committingContexts.Count, committingContexts.First().EventStream.Version, committingContexts.Last().EventStream.Version);
                    ProcessDuplicateEvent(committingContexts.First());
                }
                else if (appendResult == EventAppendResult.DuplicateCommand)
                {
                    PersistEventOneByOne(committingContexts);
                }
            },
                                                () => string.Format("[contextListCount:{0}]", committingContexts.Count),
                                                errorMessage =>
            {
                _logger.Fatal(string.Format("Batch persist event has unknown exception, the code should not be run to here, errorMessage: {0}", errorMessage));
            },
                                                retryTimes, true);
        }
コード例 #4
0
        public async Task Should_Append_EventStream()
        {
            //Arrange
            var eventStream = GetTestDomainEventStream(ObjectId.GenerateNewStringId());

            //Act
            await _store.BatchAppendAsync(new List <DomainEventStream> {
                eventStream
            });

            //Assert
            var result = await _store.FindAsync(eventStream.AggregateRootId, eventStream.Version);

            result.AggregateRootId.ShouldBe(eventStream.AggregateRootId);
            result.AggregateRootTypeName.ShouldBe(eventStream.AggregateRootTypeName);
            result.Version.ShouldBe(eventStream.Version);
            foreach (var @event in result.Events)
            {
                eventStream.Events.ToList().Select(e => e.AggregateRootStringId).ShouldContain(@event.AggregateRootStringId);
            }
            result.CommandId.ShouldBe(eventStream.CommandId);
            result.ShouldNotBeNull();
        }
コード例 #5
0
        private void BatchPersistEventAsync(IList <EventCommittingContext> committingContexts, int retryTimes)
        {
            _ioHelper.TryAsyncActionRecursively("BatchPersistEventAsync",
                                                () => _eventStore.BatchAppendAsync(committingContexts.Select(x => x.EventStream)),
                                                currentRetryTimes => BatchPersistEventAsync(committingContexts, currentRetryTimes),
                                                result =>
            {
                var eventMailBox = committingContexts.First().MailBox;
                var appendResult = result.Data;

                //针对持久化成功的聚合根,发布这些聚合根的事件到Q端
                if (appendResult.SuccessAggregateRootIdList != null && appendResult.SuccessAggregateRootIdList.Count > 0)
                {
                    var successCommittedContextDict = new Dictionary <string, IList <EventCommittingContext> >();
                    foreach (var aggregateRootId in appendResult.SuccessAggregateRootIdList)
                    {
                        var contextList = committingContexts.Where(x => x.EventStream.AggregateRootId == aggregateRootId).ToList();
                        if (contextList.Count > 0)
                        {
                            successCommittedContextDict.Add(aggregateRootId, contextList);
                        }
                    }
                    if (_logger.IsDebugEnabled)
                    {
                        _logger.DebugFormat("Batch persist events, mailboxNumber: {0}, succeedAggregateRootCount: {1}, eventStreamDetail: {2}",
                                            eventMailBox.Number,
                                            appendResult.SuccessAggregateRootIdList.Count,
                                            _jsonSerializer.Serialize(successCommittedContextDict));
                    }

                    Task.Factory.StartNew(x =>
                    {
                        var contextListDict = x as Dictionary <string, IList <EventCommittingContext> >;
                        foreach (var entry in contextListDict)
                        {
                            foreach (var committingContext in entry.Value)
                            {
                                PublishDomainEventAsync(committingContext.ProcessingCommand, committingContext.EventStream);
                            }
                        }
                    }, successCommittedContextDict);
                }

                //针对持久化出现重复的命令ID,则重新发布这些命令对应的领域事件到Q端
                if (appendResult.DuplicateCommandIdList != null && appendResult.DuplicateCommandIdList.Count > 0)
                {
                    _logger.WarnFormat("Batch persist events, mailboxNumber: {0}, duplicateCommandIdCount: {1}, detail: {2}",
                                       eventMailBox.Number,
                                       appendResult.DuplicateCommandIdList.Count,
                                       _jsonSerializer.Serialize(appendResult.DuplicateCommandIdList));

                    foreach (var commandId in appendResult.DuplicateCommandIdList)
                    {
                        var committingContext = committingContexts.FirstOrDefault(x => x.ProcessingCommand.Message.Id == commandId);
                        if (committingContext != null)
                        {
                            TryToRepublishEventAsync(committingContext, 0);
                        }
                    }
                }

                //针对持久化出现版本冲突的聚合根,则自动处理每个聚合根的冲突
                if (appendResult.DuplicateEventAggregateRootIdList != null && appendResult.DuplicateEventAggregateRootIdList.Count > 0)
                {
                    _logger.WarnFormat("Batch persist events, mailboxNumber: {0}, duplicateEventAggregateRootCount: {1}, detail: {2}",
                                       eventMailBox.Number,
                                       appendResult.DuplicateEventAggregateRootIdList.Count,
                                       _jsonSerializer.Serialize(appendResult.DuplicateEventAggregateRootIdList));

                    foreach (var aggregateRootId in appendResult.DuplicateEventAggregateRootIdList)
                    {
                        var committingContext = committingContexts.FirstOrDefault(x => x.EventStream.AggregateRootId == aggregateRootId);
                        if (committingContext != null)
                        {
                            ProcessAggregateDuplicateEvent(committingContext);
                        }
                    }
                }

                //最终,将当前的EventMailBox的本次处理标记为处理完成,然后继续可以处理下一批事件
                eventMailBox.CompleteRun();
            },
                                                () => string.Format("[contextListCount:{0}]", committingContexts.Count),
                                                null,
                                                retryTimes, true);
        }
コード例 #6
0
        private void BatchPersistEventAsync(IList <EventCommittingContext> committingContexts, int retryTimes)
        {
            if (committingContexts == null || committingContexts.Count == 0)
            {
                return;
            }

            _ioHelper.TryAsyncActionRecursively("BatchPersistEventAsync",
                                                () => _eventStore.BatchAppendAsync(committingContexts.Select(x => x.EventStream)),
                                                currentRetryTimes => BatchPersistEventAsync(committingContexts, currentRetryTimes),
                                                async result =>
            {
                var eventMailBox = committingContexts.First().MailBox;

                if (result == null)
                {
                    _logger.FatalFormat("Batch persist events success, but the persist result is null, the current event committing mailbox should be pending, mailboxNumber: {0}", eventMailBox.Number);
                    return;
                }

                //针对持久化成功的聚合根,正常发布这些聚合根的事件到Q端
                if (result.SuccessAggregateRootIdList != null && result.SuccessAggregateRootIdList.Count > 0)
                {
                    foreach (var aggregateRootId in result.SuccessAggregateRootIdList)
                    {
                        var committingContextList = committingContexts.Where(x => x.EventStream.AggregateRootId == aggregateRootId).ToList();
                        if (committingContextList.Count > 0)
                        {
                            foreach (var committingContext in committingContextList)
                            {
                                PublishDomainEventAsync(committingContext.ProcessingCommand, committingContext.EventStream);
                            }
                            if (_logger.IsDebugEnabled)
                            {
                                _logger.DebugFormat("Batch persist events success, mailboxNumber: {0}, aggregateRootId: {1}",
                                                    eventMailBox.Number,
                                                    aggregateRootId);
                            }
                        }
                    }
                }

                //针对持久化出现重复的命令ID,在命令MailBox中标记为已重复,在事件MailBox中清除对应聚合根产生的事件,且重新发布这些命令对应的领域事件到Q端
                if (result.DuplicateCommandAggregateRootIdList != null && result.DuplicateCommandAggregateRootIdList.Count > 0)
                {
                    foreach (var entry in result.DuplicateCommandAggregateRootIdList)
                    {
                        var committingContext = committingContexts.FirstOrDefault(x => x.AggregateRoot.UniqueId == entry.Key);
                        if (committingContext != null)
                        {
                            _logger.WarnFormat("Batch persist events has duplicate commandIds, mailboxNumber: {0}, aggregateRootId: {1}, commandIds: {2}",
                                               eventMailBox.Number,
                                               entry.Key,
                                               string.Join(",", entry.Value));
                            await ResetCommandMailBoxConsumingSequence(committingContext, committingContext.ProcessingCommand.Sequence, entry.Value).ConfigureAwait(false);
                            TryToRepublishEventAsync(committingContext, 0);
                        }
                    }
                }

                //针对持久化出现版本冲突的聚合根,则自动处理每个聚合根的冲突
                if (result.DuplicateEventAggregateRootIdList != null && result.DuplicateEventAggregateRootIdList.Count > 0)
                {
                    foreach (var aggregateRootId in result.DuplicateEventAggregateRootIdList)
                    {
                        var committingContext = committingContexts.FirstOrDefault(x => x.EventStream.AggregateRootId == aggregateRootId);
                        if (committingContext != null)
                        {
                            _logger.WarnFormat("Batch persist events has version confliction, mailboxNumber: {0}, aggregateRootId: {1}, conflictVersion: {2}",
                                               eventMailBox.Number,
                                               committingContext.EventStream.AggregateRootId,
                                               committingContext.EventStream.Version);

                            if (committingContext.EventStream.Version == 1)
                            {
                                await HandleFirstEventDuplicationAsync(committingContext, 0);
                            }
                            else
                            {
                                await ResetCommandMailBoxConsumingSequence(committingContext, committingContext.ProcessingCommand.Sequence, null).ContinueWith(t => { }).ConfigureAwait(false);
                            }
                        }
                    }
                }

                committingContexts.First().MailBox.CompleteRun();
            },
                                                () => string.Format("[contextListCount:{0}]", committingContexts.Count),
                                                null,
                                                retryTimes, true);
        }