private void TryPersistEvents(EventStreamContext context, Action successAction) { Func <bool> tryPersistEvents = () => { try { _eventStore.Append(context.EventStream); return(true); } catch (Exception ex) { if (ex is ConcurrentException && IsEventStreamCommitted(context.EventStream)) { return(true); } var errorMessage = string.Format("{0} raised when persisting events:{1}", ex.GetType().Name, context.EventStream.GetStreamInformation()); _logger.Error(errorMessage, ex); if (ex is ConcurrentException) { context.SetConcurrentException(new ErrorInfo(errorMessage, ex)); return(true); } return(false); } }; _retryService.TryAction("TryPersistEvents", tryPersistEvents, 3, successAction); }
private void TryDispatchEventsToEventHandlers(EventStreamContext context) { Func <bool> tryDispatchEvents = () => { var eventStream = context.EventStream; switch (eventStream.Version) { case 1: return(DispatchEventsToHandlers(eventStream)); default: var lastPublishedVersion = _eventPublishInfoStore.GetEventPublishedVersion(eventStream.AggregateRootId); if (lastPublishedVersion + 1 == eventStream.Version) { return(DispatchEventsToHandlers(eventStream)); } return(lastPublishedVersion + 1 > eventStream.Version); } }; try { _retryService.TryAction("TryDispatchEvents", tryDispatchEvents, 3, () => Clear(context)); } catch (Exception ex) { _logger.Error(string.Format("Exception raised when dispatching events:{0}", context.EventStream.GetStreamInformation()), ex); } }
public void SetUp() { _aggregateId = _fixture.Create <string>(); _cancellationToken = new CancellationToken(); _eventStreamMock = new Mock <IEventStream>(); var creditAmount1 = _fixture.Create <decimal>(); var creditAmount2 = _fixture.Create <decimal>(); var debitAmount = _fixture.Create <decimal>(); _expectedAccountBalance = creditAmount1 + creditAmount2 - debitAmount; _committedEvents = new List <object> { new AccountCreated { AccountId = _aggregateId }, new AccountCredited { Amount = creditAmount1 }, new AccountDebited { Amount = debitAmount }, new AccountCredited { Amount = creditAmount2 } }; _eventStreamContext = new EventStreamContext(_committedEvents, _fixture.Create <string>()); _eventStreamMock.Setup(x => x.ReadAsync(_aggregateId, _cancellationToken)).ReturnsAsync(_eventStreamContext); _sut = new AggregateRepository <BankAccount>(_eventStreamMock.Object); }
public async Task NotThrowException_WhenGettingAggregate_GivenEventStreamIsEmpty() { var eventStreamContext = new EventStreamContext(new List <object>(), _fixture.Create <string>()); _eventStreamMock.Setup(x => x.ReadAsync(_aggregateId, _cancellationToken)).ReturnsAsync(eventStreamContext); Func <Task> act = async() => await _sut.GetAsync(_aggregateId, CancellationToken.None); await act.Should().NotThrowAsync <Exception>(); }
/// <summary>Execute the given event stream. /// </summary> /// <param name="message"></param> /// <param name="queue"></param> public override void Execute(EventStream message, IMessageQueue <EventStream> queue) { var context = new EventStreamContext { EventStream = message, Queue = queue }; Func <bool> tryCommitEvents = () => { try { return(CommitEvents(context)); } catch (Exception ex) { _logger.Error(string.Format("Exception raised when committing events:{0}.", context.EventStream.GetStreamInformation()), ex); return(false); } }; _retryService.TryAction("TryCommitEvents", tryCommitEvents, 3, () => { }); }
private void RetryCommand(EventStreamContext context, ErrorInfo errorInfo, Action successAction) { var eventStream = context.EventStream; if (!eventStream.IsRestoreFromStorage()) { var commandInfo = _processingCommandCache.Get(eventStream.CommandId); if (commandInfo != null) { _retryCommandService.RetryCommand(commandInfo, eventStream, errorInfo, successAction); } else { _logger.ErrorFormat("The command need to retry cannot be found from command processing cache, commandId:{0}", eventStream.CommandId); } } else { _logger.InfoFormat("The command with id {0} will not be retry as the current event stream is restored from the message store.", eventStream.CommandId); } }
private bool CommitEvents(EventStreamContext context) { var synchronizeResult = TryCallSynchronizersBeforeEventPersisting(context.EventStream); switch (synchronizeResult.Status) { case SynchronizeStatus.SynchronizerConcurrentException: return(false); case SynchronizeStatus.Failed: Clear(context, synchronizeResult.ErrorInfo); return(true); default: { Action persistSuccessAction = () => { if (context.HasConcurrentException) { TryRefreshMemoryCache(context.EventStream); RetryCommand(context, context.ErrorInfo, () => FinishExecution(context.EventStream, context.Queue)); } else { TryRefreshMemoryCache(context.EventStream); TryCallSynchronizersAfterEventPersisted(context.EventStream); TryPublishEvents(context.EventStream, () => Clear(context)); } }; TryPersistEvents(context, persistSuccessAction); return(true); } } }
private void Clear(EventStreamContext context, ErrorInfo errorInfo = null) { _commandAsyncResultManager.TryComplete(context.EventStream.CommandId, context.EventStream.AggregateRootId, errorInfo); _processingCommandCache.TryRemove(context.EventStream.CommandId); FinishExecution(context.EventStream, context.Queue); }
private void Clear(EventStreamContext context) { UpdatePublishedEventStreamVersion(context.EventStream); FinishExecution(context.EventStream, context.Queue); }