/// <summary>Commit the dirty aggregate's domain events to the eventstore and publish the domain events.
        /// </summary>
        public void CommitEvent(EventProcessingContext context)
        {
            var commitEvents = new Func<bool>(() =>
            {
                try
                {
                    return CommitEvents(context);
                }
                catch (Exception ex)
                {
                    _logger.Error(string.Format("Exception raised when committing events:{0}.", context.EventStream), ex);
                    return false;
                }
            });

            _actionExecutionService.TryAction("CommitEvents", commitEvents, 3, null);
        }
 private void RetryCommand(EventProcessingContext context)
 {
     _retryCommandService.RetryCommand(context.ProcessingCommand);
 }
        private void PersistEvents(EventProcessingContext context, ActionInfo successCallback)
        {
            var persistEvents = new Func<bool>(() =>
            {
                try
                {
                    context.AppendResult = _eventStore.Append(_eventStreamConvertService.ConvertTo(context.EventStream));
                    return true;
                }
                catch (Exception ex)
                {
                    if (ex is ConcurrentException || ex is DuplicateAggregateException)
                    {
                        context.Exception = ex as ENodeException;
                        return true;
                    }
                    _logger.Error(string.Format("{0} raised when persisting events:{1}", ex.GetType().Name, context.EventStream), ex);
                    return false;
                }
            });

            _actionExecutionService.TryAction("PersistEvents", persistEvents, 3, successCallback);
        }
 private void RefreshMemoryCache(EventProcessingContext context)
 {
     try
     {
         _eventSourcingService.ReplayEvents(context.AggregateRoot, new EventStream[] { context.EventStream });
         _memoryCache.Set(context.AggregateRoot);
     }
     catch (Exception ex)
     {
         _logger.Error(string.Format("Exception raised when refreshing memory cache by event stream:{0}", context.EventStream), ex);
     }
 }
        private bool CommitEvents(EventProcessingContext context)
        {
            var synchronizerResult = SyncBeforeEventPersisting(context.EventStream);

            switch (synchronizerResult.Status)
            {
                case SynchronizeStatus.SynchronizerConcurrentException:
                    return false;
                case SynchronizeStatus.Failed:
                    context.ProcessingCommand.CommandExecuteContext.OnCommandExecuted(
                        context.ProcessingCommand.Command,
                        CommandStatus.Failed,
                        synchronizerResult.ExceptionCode,
                        synchronizerResult.ErrorMessage);
                    return true;
                default:
                {
                    var persistEventsCallback = new Func<object, bool>(obj =>
                    {
                        var currentContext = obj as EventProcessingContext;
                        var eventStream = currentContext.EventStream;

                        if (currentContext.AppendResult == EventAppendResult.Success)
                        {
                            RefreshMemoryCache(currentContext);
                            SendWaitingCommand(eventStream);
                            SyncAfterEventPersisted(eventStream);
                            PublishEvents(currentContext.ProcessingCommand.CommandExecuteContext.Items, currentContext.ProcessingCommand, eventStream);
                        }
                        else if (currentContext.AppendResult == EventAppendResult.DuplicateCommit)
                        {
                            SendWaitingCommand(eventStream);
                            var existingEventStream = GetEventStream(eventStream.AggregateRootId, eventStream.CommitId);
                            if (existingEventStream != null)
                            {
                                SyncAfterEventPersisted(existingEventStream);
                                PublishEvents(currentContext.ProcessingCommand.CommandExecuteContext.Items, currentContext.ProcessingCommand, existingEventStream);
                            }
                            else
                            {
                                _logger.ErrorFormat("Duplicate commit, but can't find the existing eventstream from eventstore. commandId:{0}, aggregateRootId:{1}, aggregateRootTypeCode:{2}",
                                    eventStream.CommitId,
                                    eventStream.AggregateRootId,
                                    eventStream.AggregateRootTypeCode);
                            }
                        }
                        else if (currentContext.Exception != null)
                        {
                            if (currentContext.Exception is DuplicateAggregateException)
                            {
                                currentContext.ProcessingCommand.CommandExecuteContext.OnCommandExecuted(
                                    currentContext.ProcessingCommand.Command,
                                    CommandStatus.Failed,
                                    0,
                                    currentContext.Exception.Message);
                            }
                            else if (currentContext.Exception is ConcurrentException)
                            {
                                RefreshMemoryCacheFromEventStore(eventStream);
                                RetryCommand(currentContext);
                            }
                        }
                        return true;
                    });

                    PersistEvents(context, new ActionInfo("PersistEventsCallback", persistEventsCallback, context, null));
                    return true;
                }
            }
        }