private async Task CommitChanges(AggregateRoot <TAggregateKey, TEventKey> aggregate) { var expectedVersion = aggregate.LastCommittedVersion; var item = await _eventStorageProvider.GetLastEventAsync(aggregate.Id); if ((item != null) && (expectedVersion == (int)StreamState.NoStream)) { throw new AggregateCreationException($"Aggregate {item.CorrelationId} can't be created as it already exists with version {item.TargetVersion + 1}"); } else if ((item != null) && ((item.TargetVersion + 1) != expectedVersion)) { throw new ConcurrencyException($"Aggregate {item.CorrelationId} has been modified externally and has an updated state. Can't commit changes."); } var changesToCommit = aggregate .GetUncommittedChanges() .Select(e => (IEvent <TEventKey, TAggregate, TAggregateKey>)e) .ToList(); //perform pre commit actions foreach (var e in changesToCommit) { DoPreCommitTasks(e); } //CommitAsync events to storage provider await _eventStorageProvider.SaveAsync(aggregate); //Publish to event publisher asynchronously foreach (var e in changesToCommit) { if (_eventPublisher != null) { await _eventPublisher.PublishAsync(e); } } //If the Aggregate implements snapshottable if ((aggregate is ISnapshottable <TSnapshotKey, TAggregateKey, TSnapshot> snapshottable) && (_snapshotStorageProvider != null)) { //Every N events we save a snapshot if ((aggregate.CurrentVersion >= _snapshotStorageProvider.SnapshotFrequency) && ( (changesToCommit.Count >= _snapshotStorageProvider.SnapshotFrequency) || (aggregate.CurrentVersion % _snapshotStorageProvider.SnapshotFrequency < changesToCommit.Count) || (aggregate.CurrentVersion % _snapshotStorageProvider.SnapshotFrequency == 0) ) ) { var snapshot = snapshottable.TakeSnapshot(); await _snapshotStorageProvider.SaveSnapshotAsync(snapshot); } } aggregate.MarkChangesAsCommitted(); }
private async Task CommitChanges(TAggregate aggregate) { var expectedVersion = aggregate.LastCommittedVersion; var item = await _eventStorageProvider.GetLastEventAsync <TAggregate, TAggregateKey>(aggregate.Id); if ((item != null)) { if (expectedVersion == (long)StreamState.NoStream) { throw new AggregateCreationException($"Aggregate {item.CorrelationId} can't be created as it already exists with version {item.TargetVersion + 1}"); } if ((item.TargetVersion + 1) != expectedVersion) { throw new ConcurrencyException($"Aggregate {item.CorrelationId} has been modified externally and has an updated state. Can't commit changes."); } } var changesToCommit = aggregate .GetUncommittedChanges() .Cast <IEvent <TAggregate, TAggregateKey, TEventKey> >() .ToList(); //perform pre commit actions DoPreCommitTasks(changesToCommit); //CommitAsync events to storage provider await _eventStorageProvider.SaveAsync <TAggregate, TAggregateKey>(aggregate.Id, changesToCommit); //Publish to event publisher asynchronously await PublishEventsAsync(changesToCommit); //If the Aggregate implements snapshottable await SaveSnapshotAsync(aggregate, changesToCommit); //Finally mark them committed aggregate.MarkChangesAsCommitted(); }