public Task <Event> GetLastEventAsync(Guid aggregateId) => storage.GetLastEventAsync(aggregateId);
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; } }