public Task <AsyncTaskResult <CommandAddResult> > AddAsync(HandledCommand handledCommand) { var record = ConvertTo(handledCommand); return(_ioHelper.TryIOFuncAsync <AsyncTaskResult <CommandAddResult> >(async() => { try { using (var connection = GetConnection()) { await connection.InsertAsync(record, _commandTable); return new AsyncTaskResult <CommandAddResult>(AsyncTaskStatus.Success, null, CommandAddResult.Success); } } catch (SqlException ex) { if (ex.Number == 2627 && ex.Message.Contains(_primaryKeyName)) { return new AsyncTaskResult <CommandAddResult>(AsyncTaskStatus.Success, null, CommandAddResult.DuplicateCommand); } return new AsyncTaskResult <CommandAddResult>(AsyncTaskStatus.IOException, ex.Message, CommandAddResult.Failed); } catch (Exception ex) { return new AsyncTaskResult <CommandAddResult>(AsyncTaskStatus.IOException, ex.Message, CommandAddResult.Failed); } }, "AddCommandAsync")); }
public CommandAddResult Add(HandledCommand handledCommand) { var record = ConvertTo(handledCommand); return _ioHelper.TryIOFunc(() => { using (var connection = GetConnection()) { try { connection.Insert(record, _commandTable); return CommandAddResult.Success; } catch (SqlException ex) { if (ex.Number == 2627) { if (ex.Message.Contains(_primaryKeyName)) { return CommandAddResult.DuplicateCommand; } } throw; } } }, "AddCommand"); }
private void CommitChangesAsync(ProcessingCommand processingCommand, IApplicationMessage message, int retryTimes) { var command = processingCommand.Message; var handledCommand = new HandledCommand( command, aggregateRootId: command.AggregateRootId, message: message); _ioHelper.TryAsyncActionRecursively <AsyncTaskResult <CommandAddResult> >("AddCommandAsync", () => _commandStore.AddAsync(handledCommand), currentRetryTimes => CommitChangesAsync(processingCommand, message, currentRetryTimes), result => { var commandAddResult = result.Data; if (commandAddResult == CommandAddResult.Success) { PublishMessageAsync(processingCommand, message, 0); } else if (commandAddResult == CommandAddResult.DuplicateCommand) { HandleDuplicatedCommandAsync(processingCommand, 0); } else { NotifyCommandExecuted(processingCommand, CommandStatus.Failed, null, "Add command async failed."); } }, () => string.Format("[handledCommand:{0}]", handledCommand), () => NotifyCommandExecuted(processingCommand, CommandStatus.Failed, null, "Add command async failed."), retryTimes); }
public Task <AsyncTaskResult <CommandAddResult> > AddAsync(HandledCommand handledCommand) { var record = ConvertTo(handledCommand); return(_ioHelper.TryIOFuncAsync(async() => { try { using (var connection = GetConnection()) { await connection.InsertAsync(record, _tableName); return new AsyncTaskResult <CommandAddResult>(AsyncTaskStatus.Success, null, CommandAddResult.Success); } } catch (SqlException ex) { if (ex.Number == 2601 && ex.Message.Contains(_uniqueIndexName)) { return new AsyncTaskResult <CommandAddResult>(AsyncTaskStatus.Success, null, CommandAddResult.DuplicateCommand); } _logger.Error(string.Format("Add handled command has sql exception, handledCommand: {0}", handledCommand), ex); throw; } catch (Exception ex) { _logger.Error(string.Format("Add handled command has unkown exception, handledCommand: {0}", handledCommand), ex); throw; } }, "AddCommandAsync")); }
public Task<AsyncTaskResult<CommandAddResult>> AddAsync(HandledCommand handledCommand) { var record = ConvertTo(handledCommand); return _ioHelper.TryIOFuncAsync<AsyncTaskResult<CommandAddResult>>(async () => { try { using (var connection = GetConnection()) { await connection.InsertAsync(record, _commandTable); return new AsyncTaskResult<CommandAddResult>(AsyncTaskStatus.Success, null, CommandAddResult.Success); } } catch (SqlException ex) { if (ex.Number == 2627 && ex.Message.Contains(_primaryKeyName)) { return new AsyncTaskResult<CommandAddResult>(AsyncTaskStatus.Success, null, CommandAddResult.DuplicateCommand); } _logger.Error(string.Format("Add handled command has sql exception, handledCommand: {0}", handledCommand), ex); return new AsyncTaskResult<CommandAddResult>(AsyncTaskStatus.IOException, ex.Message, CommandAddResult.Failed); } catch (Exception ex) { _logger.Error(string.Format("Add handled command has unkown exception, handledCommand: {0}", handledCommand), ex); return new AsyncTaskResult<CommandAddResult>(AsyncTaskStatus.Failed, ex.Message, CommandAddResult.Failed); } }, "AddCommandAsync"); }
public CommandAddResult Add(HandledCommand handledCommand) { var record = ConvertTo(handledCommand); return(_ioHelper.TryIOFunc(() => { using (var connection = GetConnection()) { try { connection.Insert(record, _commandTable); return CommandAddResult.Success; } catch (SqlException ex) { if (ex.Number == 2627) { if (ex.Message.Contains(_primaryKeyName)) { return CommandAddResult.DuplicateCommand; } } throw; } } }, "AddCommand")); }
private void CommitChangesAsync(ProcessingCommand processingCommand, IApplicationMessage message, int retryTimes) { var command = processingCommand.Message; var handledCommand = new HandledCommand(command.Id, command.AggregateRootId, message); _ioHelper.TryAsyncActionRecursively <AsyncTaskResult <CommandAddResult> >("AddCommandAsync", () => _commandStore.AddAsync(handledCommand), currentRetryTimes => CommitChangesAsync(processingCommand, message, currentRetryTimes), result => { var commandAddResult = result.Data; if (commandAddResult == CommandAddResult.Success) { PublishMessageAsync(processingCommand, message, 0); } else if (commandAddResult == CommandAddResult.DuplicateCommand) { HandleDuplicatedCommandAsync(processingCommand, 0); } else { _logger.ErrorFormat("Add command async failed, commandType:{0}, commandId:{1}, aggregateRootId:{2}", command.GetType().Name, command.Id, command.AggregateRootId); NotifyCommandExecuted(processingCommand, CommandStatus.Failed, typeof(string).FullName, "Add command async failed."); } }, () => string.Format("[handledCommand:{0}]", handledCommand), errorMessage => NotifyCommandExecuted(processingCommand, CommandStatus.Failed, typeof(string).Name, errorMessage ?? "Add command async failed."), retryTimes); }
public Task <AsyncTaskResult <CommandAddResult> > AddAsync(HandledCommand handledCommand) { var record = ConvertTo(handledCommand); return(_ioHelper.TryIOFuncAsync <AsyncTaskResult <CommandAddResult> >(async() => { try { using (var connection = GetConnection()) { await connection.InsertToMySqlAsync(record, _tableName); return new AsyncTaskResult <CommandAddResult>(AsyncTaskStatus.Success, null, CommandAddResult.Success); } } catch (DbException ex) { //if (ex.Number == 2627 && ex.Message.Contains(_primaryKeyName)) //{ // return new AsyncTaskResult<CommandAddResult>(AsyncTaskStatus.Success, null, CommandAddResult.DuplicateCommand); //} _logger.Error(string.Format("Add handled command has sql exception, handledCommand: {0}", handledCommand), ex); return new AsyncTaskResult <CommandAddResult>(AsyncTaskStatus.IOException, ex.Message, CommandAddResult.Failed); } catch (Exception ex) { _logger.Error(string.Format("Add handled command has unkown exception, handledCommand: {0}", handledCommand), ex); return new AsyncTaskResult <CommandAddResult>(AsyncTaskStatus.Failed, ex.Message, CommandAddResult.Failed); } }, "AddCommandAsync")); }
public Task <AsyncTaskResult <CommandAddResult> > AddAsync(HandledCommand handledCommand) { var record = ConvertTo(handledCommand); return(_ioHelper.TryIOFuncAsync(async() => { try { using (var connection = GetConnection()) { string sql = string.Format( "INSERT INTO `{0}` (CommandId,CreatedOn,AggregateRootId,MessagePayload,MessageTypeName) VALUES (@CommandId,@CreatedOn,@AggregateRootId,@MessagePayload,@MessageTypeName)", _tableName); await connection.ExecuteAsync(sql, record); return new AsyncTaskResult <CommandAddResult>(AsyncTaskStatus.Success, null, CommandAddResult.Success); } } catch (MySqlException ex) { if (ex.Number == 1062 && ex.Message.Contains(_uniqueIndexName)) { return new AsyncTaskResult <CommandAddResult>(AsyncTaskStatus.Success, null, CommandAddResult.DuplicateCommand); } _logger.Error(ex.InnerException); _logger.Error(string.Format("Add handled command has sql exception, handledCommand: {0}", handledCommand), ex); throw; } catch (Exception ex) { _logger.Error(string.Format("Add handled command has unkown exception, handledCommand: {0}", handledCommand), ex); throw; } }, "AddCommandAsync")); }
private CommandAddResult Add(HandledCommand handledCommand) { if (_handledCommandDict.TryAdd(handledCommand.CommandId, handledCommand)) { return(CommandAddResult.Success); } return(CommandAddResult.DuplicateCommand); }
public CommandAddResult Add(HandledCommand handledCommand) { if (_handledCommandDict.TryAdd(handledCommand.Command.Id, handledCommand)) { return CommandAddResult.Success; } return CommandAddResult.DuplicateCommand; }
private CommandRecord ConvertTo(HandledCommand handledCommand) { return(new CommandRecord { CommandId = handledCommand.CommandId, AggregateRootId = handledCommand.AggregateRootId, MessagePayload = handledCommand.Message != null?_jsonSerializer.Serialize(handledCommand.Message) : null, MessageTypeName = handledCommand.Message != null?_typeNameProvider.GetTypeName(handledCommand.Message.GetType()) : null, CreatedOn = DateTime.Now, }); }
private CommandRecord ConvertTo(HandledCommand handledCommand) { return(new CommandRecord { CommandId = handledCommand.Command.Id, CommandTypeCode = _typeCodeProvider.GetTypeCode(handledCommand.Command.GetType()), AggregateRootId = handledCommand.AggregateRootId, AggregateRootTypeCode = handledCommand.AggregateRootTypeCode, Timestamp = DateTime.Now, Payload = _jsonSerializer.Serialize(handledCommand.Command), Message = handledCommand.Message != null?_jsonSerializer.Serialize(handledCommand.Message) : null, MessageTypeCode = handledCommand.Message != null?_typeCodeProvider.GetTypeCode(handledCommand.Message.GetType()) : 0, }); }
private void CommitAggregateChanges(ProcessingCommand processingCommand) { var command = processingCommand.Message; var context = processingCommand.CommandExecuteContext; var trackedAggregateRoots = context.GetTrackedAggregateRoots(); var dirtyAggregateRootChanges = trackedAggregateRoots.ToDictionary(x => x, x => x.GetChanges()).Where(x => x.Value.Any()); var dirtyAggregateRootCount = dirtyAggregateRootChanges.Count(); //如果当前command没有对任何聚合根做修改,则认为当前command已经处理结束,返回command的结果为NothingChanged if (dirtyAggregateRootCount == 0) { _logger.DebugFormat("No aggregate created or modified by command. commandType:{0}, commandId:{1}", command.GetType().Name, command.Id); NotifyCommandExecuted(processingCommand, CommandStatus.NothingChanged, null, null); return; } //如果被创建或修改的聚合根多于一个,则认为当前command处理失败,一个command只能创建或修改一个聚合根; else if (dirtyAggregateRootCount > 1) { var dirtyAggregateTypes = string.Join("|", dirtyAggregateRootChanges.Select(x => x.Key.GetType().Name)); var errorMessage = string.Format("Detected more than one aggregate created or modified by command. commandType:{0}, commandId:{1}, dirty aggregate types:{2}", command.GetType().Name, command.Id, dirtyAggregateTypes); _logger.ErrorFormat(errorMessage); NotifyCommandExecuted(processingCommand, CommandStatus.Failed, null, errorMessage); return; } //获取当前被修改的聚合根 var dirtyAggregateRootChange = dirtyAggregateRootChanges.Single(); var dirtyAggregateRoot = dirtyAggregateRootChange.Key; var changedEvents = dirtyAggregateRootChange.Value; //构造出一个事件流对象 var eventStream = BuildDomainEventStream(dirtyAggregateRoot, changedEvents, processingCommand); //如果当前command处于并发冲突的重试中,则直接提交该command产生的事件,因为该command肯定已经在command store中了 if (processingCommand.ConcurrentRetriedCount > 0) { _eventService.CommitDomainEventAsync(new EventCommittingContext(dirtyAggregateRoot, eventStream, processingCommand)); return; } var handledAggregateCommand = new HandledCommand( command, eventStream.AggregateRootId, eventStream.AggregateRootTypeCode); CommitAggregateChangesAsync(processingCommand, dirtyAggregateRoot, eventStream, handledAggregateCommand, 0); }
private void CommitChangesAsync(ProcessingCommand processingCommand, bool success, IApplicationMessage message, string errorMessage, int retryTimes) { var command = processingCommand.Message; var handledCommand = new HandledCommand(command.Id, command.AggregateRootId, message); _ioHelper.TryAsyncActionRecursively("AddCommandAsync", () => _commandStore.AddAsync(handledCommand), currentRetryTimes => CommitChangesAsync(processingCommand, success, message, errorMessage, currentRetryTimes), result => { var commandAddResult = result.Data; if (commandAddResult == CommandAddResult.Success) { if (success) { if (message != null) { PublishMessageAsync(processingCommand, message, 0); } else { CompleteCommand(processingCommand, CommandStatus.Success, null, null); } } else { CompleteCommand(processingCommand, CommandStatus.Failed, typeof(string).FullName, errorMessage); } } else if (commandAddResult == CommandAddResult.DuplicateCommand) { HandleDuplicatedCommandAsync(processingCommand, 0); } }, () => string.Format("[handledCommand:{0}]", handledCommand), error => { _logger.Fatal(string.Format("Add command has unknown exception, the code should not be run to here, errorMessage: {0}", error)); }, retryTimes, true); }
public Task <AsyncTaskResult <CommandAddResult> > AddAsync(HandledCommand handledCommand) { if (_currentFailedCount < _expectAddFailedCount) { _currentFailedCount++; if (_failedType == FailedType.UnKnownException) { throw new Exception("AddCommandAsyncUnKnownException" + _currentFailedCount); } else if (_failedType == FailedType.IOException) { throw new IOException("AddCommandAsyncIOException" + _currentFailedCount); } else if (_failedType == FailedType.TaskIOException) { return(Task.FromResult(new AsyncTaskResult <CommandAddResult>(AsyncTaskStatus.Failed, "AddCommandAsyncError" + _currentFailedCount))); } } return(Task.FromResult(new AsyncTaskResult <CommandAddResult>(AsyncTaskStatus.Success, null, Add(handledCommand)))); }
public Task <AsyncTaskResult <CommandAddResult> > AddAsync(HandledCommand handledCommand) { return(Task.FromResult <AsyncTaskResult <CommandAddResult> >(new AsyncTaskResult <CommandAddResult>(AsyncTaskStatus.Success, null, Add(handledCommand)))); }
private void TryToRetryCommandForExceptionAsync(ProcessingCommand processingCommand, HandledCommand existingHandledCommand, ICommandHandlerProxy commandHandler, Exception exception, int retryTimes) { var command = processingCommand.Message; //到这里,说明当前command执行遇到异常,然后该command在commandStore中存在, //但是在eventStore中不存在,此时可以理解为该command还未被成功执行,此时做如下操作: //1.将command从commandStore中移除 //2.根据eventStore里的事件刷新缓存,目的是为了还原聚合根到最新状态,因为该聚合根的状态有可能已经被污染 //3.重试该command _ioHelper.TryAsyncActionRecursively <AsyncTaskResult>("RemoveCommandAsync", () => _commandStore.RemoveAsync(command.Id), currentRetryTimes => TryToRetryCommandForExceptionAsync(processingCommand, existingHandledCommand, commandHandler, exception, currentRetryTimes), result => { _memoryCache.RefreshAggregateFromEventStore(existingHandledCommand.AggregateRootTypeCode, existingHandledCommand.AggregateRootId); RetryCommand(processingCommand); }, () => string.Format("[commandId:{0}]", command.Id), () => NotifyCommandExecuted(processingCommand, CommandStatus.Failed, null, "Remove command async failed."), retryTimes); }
private void HandleExistingHandledCommandForExceptionAsync(ProcessingCommand processingCommand, HandledCommand existingHandledCommand, ICommandHandlerProxy commandHandler, Exception exception, int retryTimes) { var command = processingCommand.Message; var aggregateRootId = existingHandledCommand.AggregateRootId; _ioHelper.TryAsyncActionRecursively <AsyncTaskResult <DomainEventStream> >("FindEventStreamByCommandIdAsync", () => _eventStore.FindAsync(aggregateRootId, command.Id), currentRetryTimes => HandleExistingHandledCommandForExceptionAsync(processingCommand, existingHandledCommand, commandHandler, exception, currentRetryTimes), result => { var existingEventStream = result.Data; if (existingEventStream != null) { _eventService.PublishDomainEventAsync(processingCommand, existingEventStream); } else { LogCommandExecuteException(processingCommand, commandHandler, exception); TryToRetryCommandForExceptionAsync(processingCommand, existingHandledCommand, commandHandler, exception, 0); } }, () => string.Format("[aggregateRootId:{0}, commandId:{1}]", aggregateRootId, command.Id), () => NotifyCommandExecuted(processingCommand, CommandStatus.Failed, null, "Find event stream by command id async failed."), retryTimes); }
private void HandleExistingHandledAggregateAsync(ProcessingCommand processingCommand, IAggregateRoot dirtyAggregateRoot, DomainEventStream eventStream, HandledCommand existingHandledCommand, int retryTimes) { var command = processingCommand.Message; _ioHelper.TryAsyncActionRecursively <AsyncTaskResult <DomainEventStream> >("FindEventStreamByCommandIdAsync", () => _eventStore.FindAsync(existingHandledCommand.AggregateRootId, command.Id), currentRetryTimes => HandleExistingHandledAggregateAsync(processingCommand, dirtyAggregateRoot, eventStream, existingHandledCommand, currentRetryTimes), result => { var existingEventStream = result.Data; if (existingEventStream != null) { //如果当前command已经被持久化过了,且该command产生的事件也已经被持久化了,则只要再做一遍发布事件的操作 _eventService.PublishDomainEventAsync(processingCommand, existingEventStream); } else { //如果当前command已经被持久化过了,但事件没有被持久化,则需要重新提交当前command所产生的事件; _eventService.CommitDomainEventAsync(new EventCommittingContext(dirtyAggregateRoot, eventStream, processingCommand)); } }, () => string.Format("[aggregateRootId:{0}, commandId:{1}]", existingHandledCommand.AggregateRootId, command.Id), () => NotifyCommandExecuted(processingCommand, CommandStatus.Failed, null, "Find event stream by command id async failed."), retryTimes); }
private void CommitAggregateChangesAsync(ProcessingCommand processingCommand, IAggregateRoot dirtyAggregateRoot, DomainEventStream eventStream, HandledCommand handledCommand, int retryTimes) { _ioHelper.TryAsyncActionRecursively <AsyncTaskResult <CommandAddResult> >("AddCommandAsync", () => _commandStore.AddAsync(handledCommand), currentRetryTimes => CommitAggregateChangesAsync(processingCommand, dirtyAggregateRoot, eventStream, handledCommand, currentRetryTimes), result => { var commandAddResult = result.Data; if (commandAddResult == CommandAddResult.Success) { _eventService.CommitDomainEventAsync(new EventCommittingContext(dirtyAggregateRoot, eventStream, processingCommand)); } else if (commandAddResult == CommandAddResult.DuplicateCommand) { HandleAggregateDuplicatedCommandAsync(processingCommand, dirtyAggregateRoot, eventStream, 0); } else { NotifyCommandExecuted(processingCommand, CommandStatus.Failed, null, "Add command async failed."); } }, () => string.Format("[handledCommand:{0}]", handledCommand), () => NotifyCommandExecuted(processingCommand, CommandStatus.Failed, null, "Add command async failed."), retryTimes); }
public Task<AsyncTaskResult<CommandAddResult>> AddAsync(HandledCommand handledCommand) { return Task.FromResult<AsyncTaskResult<CommandAddResult>>(new AsyncTaskResult<CommandAddResult>(AsyncTaskStatus.Success, null, Add(handledCommand))); }
private CommandRecord ConvertTo(HandledCommand handledCommand) { return new CommandRecord { CommandId = handledCommand.CommandId, AggregateRootId = handledCommand.AggregateRootId, MessagePayload = handledCommand.Message != null ? _jsonSerializer.Serialize(handledCommand.Message) : null, MessageTypeName = handledCommand.Message != null ? _typeNameProvider.GetTypeName(handledCommand.Message.GetType()) : null, CreatedOn = DateTime.Now, }; }
private CommandRecord ConvertTo(HandledCommand handledCommand) { return new CommandRecord { CommandId = handledCommand.CommandId, AggregateRootId = handledCommand.AggregateRootId, Message = handledCommand.Message != null ? _jsonSerializer.Serialize(handledCommand.Message) : null, MessageTypeCode = handledCommand.Message != null ? _typeCodeProvider.GetTypeCode(handledCommand.Message.GetType()) : 0, Timestamp = DateTime.Now, }; }