public async ValueTask <RepositoryEntityState> PreSaveChangesAsync(RepositoryEntityState entityState, object entity, CancellationToken cancellationToken = default) { if (entity is IDomainEventProvider domainEventProvider) { var entityEvents = domainEventProvider.GetDomainEvents(); var completedEventCount = 0; if (entityEvents == null || entityEvents.Count == 0) { return(entityState); } foreach (var @event in entityEvents) { try { await _eventDispatcher.DispatchAsync(@event); completedEventCount++; } catch (Exception ex) { _logger.LogWarning(ex, "There has a error when dispatch domain event."); } } if (completedEventCount != entityEvents.Count) { //count is not equal. prove the existence of failed events } } return(entityState); }
private async Task DispatchEventsToBeProcessed(CancellationToken cancellationToken) { var eventId = Guid.Empty; try { _logger.Debug("About to dispatch EventsToBeProcessed..."); foreach (var @event in _eventBag.EventsToBeProcessed.ToList()) { eventId = @event.Id; _logger.Debug($"Publishing event. Id: {@event.Id} SourceType: {@event.SourceTypeName}"); await _eventDispatcher.DispatchAsync(@event, cancellationToken); _eventBag.EventsToBeProcessed.Remove(@event); if (_cqrsOptions.PurgeEventsToBeProcessed) { await PurgeEvent(@event, cancellationToken); } } } catch (Exception ex) { _logger.Error($"Dispatching failed. Id: {eventId}"); _logger.Error(ex); } }
/// <summary> /// Asynchronously processes an event queue by dispatching the events /// </summary> /// <param name="preTransaction">True, if pre-transaction handlers required</param> /// <param name="queue">The event queue to process</param> private async Task ProcessEventQueue(IEventQueue queue, bool preTransaction = false) { var queueTasks = new List <Task>(); while (false == queue.IsEmpty()) { var nextItem = queue.GetNext(); var dispatchTask = _eventDispatcher.DispatchAsync(nextItem.Event, preTransaction); queueTasks.Add(dispatchTask); // We don't want to log pre-transaction events if (false == preTransaction) { var logTask = _eventLogger.LogEventAsync ( nextItem.AggregateKey, nextItem.AggregateType, nextItem.Event ); queueTasks.Add(logTask); } } await Task.WhenAll(queueTasks).ConfigureAwait(false); }
public async Task <TEvent> DispatchAsync <TEvent>(ICommand <TEvent> command, CancellationToken cancellationToken) where TEvent : IEvent { var commandHandlerType = s_commandHandlerGenericType.MakeGenericType(command.GetType(), typeof(TEvent)); var handleMethod = commandHandlerType.GetTypeInfo().GetMethod("HandleAsync"); var commandHandler = _componentContext.Resolve(commandHandlerType); TEvent @event; @event = await(dynamic) handleMethod.Invoke(commandHandler, new object[] { command, cancellationToken }); try { await _eventDispatcher.DispatchAsync(@event, cancellationToken); } catch (Exception exception) { var eventName = @event.GetType().FullName; var exceptionName = exception.GetType().FullName; _logger.LogError ( new EventId(), exception, "Exception {ExceptionName} thrown with message {ExceptionMessage} when handling event {EventName}", exceptionName, exception.Message, eventName ); } return(@event); }
public async Task CreateAsync(string email) { var user = new User(email); //Store the user somehwere safe using the repository etc. //Dispatch all of the user events await _eventDispatcher.DispatchAsync(user.Events.ToArray()); }
private async Task DispatchEvents() { var entities = ChangeTracker .Entries <Entity>() .Where(x => x.Entity.DomainEvents != null && x.Entity.DomainEvents.Any()) .Select(x => x.Entity); await eventDispatcher.DispatchAsync(entities); }
public override async Task <int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken()) { var affectedRows = await base.SaveChangesAsync(cancellationToken); await _eventDispatcher.DispatchAsync(this); return(affectedRows); }
public async Task CreateAsync(string email) { var user = new User(email); // store await _eventDispatcher.DispatchAsync(user.Events.ToArray()); }
public async Task SignUpAsync(Guid id, string email, string password, string role) { var user = await _userFactory.CreateAsync(id, email, password, role); await _userRepository.CreateAsync(user); await _eventDispatcher.DispatchAsync(user.Events.ToArray()); }
private async Task DispatchEventsAsync(CancellationToken cancellationToken = default) { var entities = ChangeTracker .Entries <EntityBase>() .Where(x => x.Entity.DomainEvents != null && x.Entity.DomainEvents.Any()) .Select(x => x.Entity); await _eventDispatcher.DispatchAsync(entities, cancellationToken); }
public async Task <IEventSourcedAggregate <TAggregate> > RetrieveAsync(Guid id) { var eventList = await _eventRepository.RetriveEventsAsync <TAggregate>(id); var aggregate = new RecordedAggregate <TAggregate>(id, eventList.AggregateVersion, eventList.DomainEvents, this, _eventDispatcher); foreach (var @event in eventList.DomainEvents) { await _eventDispatcher.DispatchAsync(aggregate.State, @event); } return(aggregate); }
private async Task DispatchDomainEvents() { var domainEventEntities = ChangeTracker.Entries <IAggregateRoot>() .Select(po => po.Entity) .Where(po => po.Events.Any()) .ToArray(); foreach (var entity in domainEventEntities) { foreach (var @event in entity.Events) { await _eventDispatcher.DispatchAsync(@event); } } }
public async Task ProcessAsync <TCommand>(TCommand command) where TCommand : CommandBase { foreach (var commandHandler in _commandHandlers.Where(e => e.GetCommandType() == command.GetType())) { var aggregate = await commandHandler.UpdatedAggregateAsync(command); if (aggregate != null) { var newEvents = aggregate.UncommittedEvents; await _aggregateRepo.AddOrUpdateAsync(aggregate); await _eventDispatcher.DispatchAsync(newEvents); } } }
public ISubscriber SubscribeEvent <TEvent>(string @namespace = null, string queueName = null, Func <TEvent, MiddlinkException, IRejectedEvent> onError = null) where TEvent : IDomainEvent { _busClient.SubscribeAsync <TEvent>((@event, correlationContext) => { return(TryHandleAsync(@event, correlationContext, () => { IEventDispatcher dispatcher = _appServiceProvider.CreateScope().ServiceProvider.GetService <IEventDispatcher>(); return dispatcher.DispatchAsync(@event, correlationContext); }, onError)); }, @namespace); return(this); }
public Task HandleAsync( ICommandHandlingContext <LogInUser> context, CancellationToken cancellationToken = default) { ExecutionContext.CurrentUser = new User { Name = context.Command.Name, LoggedInAt = DateTime.Now }; _eventDispatcher.DispatchAsync(new UserWasLoggedIn( ExecutionContext.CurrentUser.Name, ExecutionContext.CurrentUser.LoggedInAt), cancellationToken); return(Task.CompletedTask); }
public async Task <ProductOut> DeleteByIdAsync(Guid productId) { productId.NotNullOrDefault(nameof(productId)); var product = await _productRepository.GetAsync(productId); if (product != null) { await _productRepository.DeleteAsync(product); await _eventDispatcher.DispatchAsync(new ProductDeletedEvent(productId)); return(_mapper.Map <ProductOut>(product)); } else { throw new MSFrameworkException(110, "Product is not exists"); } }
public async Task StartAsync(CancellationToken cancellationToken) { var streamName = RedisExtensions.GetPrimaryStream(); IDatabase db = _connectionMultiplexer.GetDatabase(); var batchSize = _configuration.BatchSize; while (true) { if (cancellationToken.IsCancellationRequested) { break; } var checkpoint = await _checkPoint.GetCheckpoint <T>(); var streamInfo = db.StreamInfo(streamName); if (streamInfo.LastEntry.Id == checkpoint) { await Task.Delay(_configuration.Delay, cancellationToken); continue; } var currentSlice = await db.StreamReadAsync(streamName, checkpoint, batchSize); foreach (var streamEntry in currentSlice) { foreach (var streamEntryValue in streamEntry.Values) { var @event = JsonConvert.DeserializeObject <AggregateEvent>(streamEntryValue.Value.ToString(), _serializerSettings); await _eventDispatcher.DispatchAsync(@event); await _checkPoint.SetCheckpoint <T>(streamEntry.Id); } } } }
private async Task ProcessDomainEvents(AggregateRoot root) { await _eventDispatcher.DispatchAsync(root.DomainEvents); root.ClearDomainEvents(); }
public async Task CommitAsync() { try { foreach (var aggregate in trackedAggregates.Values) { if (!aggregate.HasEventSourcing()) { throw new AggregateFeatureNotFoundException($"Aggregate '{aggregate.GetType().Name}:{aggregate.Id}' must has '{nameof(EventSourcingAggregateFeature)}' to uses '{nameof(EventSourcingRepository<TAggregate>)}'."); } var expectedVersion = aggregate.GetLastCommittedVersion(); var lastEvent = await eventStorage.GetLastEventAsync(aggregate.Id); if ((lastEvent != null) && (expectedVersion == 0)) { throw new AggregateCreationException($"Aggregate '{aggregate.Id}' can't be created as it already exists with version {lastEvent.EventSourcing().TargetVersion + 1}"); } else if ((lastEvent != null) && ((lastEvent.EventSourcing().TargetVersion + 1) != expectedVersion)) { throw new ConcurrencyException($"Aggregate '{aggregate.Id}' has been modified externally and has an updated state. Can't commit changes."); } var changesToCommit = aggregate.GetPendingEvents(); //perform pre commit actions foreach (var e in changesToCommit) { e.EventSourcing().EventCommittedTimestamp = DateTime.UtcNow; } //CommitAsync events to storage provider await eventStorage.CommitAsync(aggregate.Id, changesToCommit); aggregate.EventSourcing().LastCommittedVersion = aggregate.GetCurrentVersion(); // If the Aggregate is snapshottable if (aggregate.IsSnapshottable()) { if (aggregate.GetCurrentVersion() - aggregate.GetSnapshotVersion() > aggregate.GetSnapshotFrequency()) { await snapshotStorage.SaveSnapshotAsync(aggregate.GetSnapshot()); aggregate.EventSourcing().SnapshotVersion = aggregate.GetCurrentVersion(); } } // Dispatch events asynchronously foreach (var e in changesToCommit) { await eventDispatcher.DispatchAsync(e); } aggregate.ClearPendingEvents(); } trackedAggregates.Clear(); } catch (Exception ex) { log.Error($"Error '{ex.GetType().Name}' in '{nameof(EventSourcingRepository<TAggregate>)}.{nameof(CommitAsync)}': {ex.Message}", ex); throw; } }
public async Task Consume(ConsumeContext <TEvent> context) { await _eventDispatcher .DispatchAsync(context.Message, context.CancellationToken) .ConfigureAwait(false); }
public async Task DispatchEventAsync(IDomainEvent @event) { await _eventDispatcher.DispatchAsync(State, @event); }