/// <summary> /// Call <see cref="IEventStore.SaveAsync"/> in <see cref="IEventStore"/> passing aggregates. /// </summary> public virtual async Task SaveChangesAsync() { _logger.Log(LogLevel.Information, $"Called method: {nameof(Session)}.{nameof(SaveChangesAsync)}."); if (!_externalTransaction) { _eventStore.BeginTransaction(); } // If transaction called externally, the client should care with transaction. try { _logger.Log(LogLevel.Information, "Begin iterate in collection of aggregate."); foreach (var aggregate in _aggregates) { var serializedEvents = aggregate.ToSerialized(_metadataProviders, _eventSerializer); if (_snapshotStrategy.ShouldMakeSnapshot(aggregate)) { await aggregate.TakeSnapshot(_eventStore, _snapshotSerializer).ConfigureAwait(false); } await _eventStore.SaveAsync(serializedEvents).ConfigureAwait(false); await _eventPublisher.PublishAsync <IDomainEvent>(aggregate.UncommitedEvents).ConfigureAwait(false); aggregate.UpdateVersion(aggregate.Sequence); aggregate.ClearUncommitedEvents(); } _logger.Log(LogLevel.Information, "End iterate."); _aggregates.Clear(); await _eventPublisher.CommitAsync().ConfigureAwait(false); } catch (Exception e) { _logger.Log(LogLevel.Error, e.Message, e); if (!_externalTransaction) { Rollback(); } throw; } if (!_externalTransaction) { await _eventStore.CommitAsync().ConfigureAwait(false); } }
/// <inheritdoc /> public virtual async Task SaveChangesAsync() { _logger.LogInformation($"Called method: {nameof(Session)}.{nameof(SaveChangesAsync)}."); if (!_externalTransaction) { _transaction.BeginTransaction(); } // If transaction called externally, the client should care with transaction. try { _logger.LogInformation("Serializing events."); var uncommittedEvents = _aggregates.SelectMany(e => e.UncommittedEvents) .OrderBy(o => o.CreatedAt) .Cast <UncommittedEvent>() .Select(GenerateMetadata) .Select(e => new { UncommitedEvent = e, EventWrapper = EventWrapperType.MakeGenericType(e.Data.GetType()), Event = e.Data, Metadata = e.Metadata }) .Select(e => new { EventWrapper = (IEventWrapper)Activator.CreateInstance(e.EventWrapper, e.Event, e.Metadata), UncommittedEvent = e.UncommitedEvent }) .ToList(); foreach (var uncommittedEvent in uncommittedEvents.Select(e => e.UncommittedEvent)) { _eventsMetadataService.Add(uncommittedEvent.Data, uncommittedEvent.Metadata); } _logger.LogInformation("Saving events on Event Store."); await _eventStore.AppendAsync(uncommittedEvents.Select(e => e.UncommittedEvent)).ConfigureAwait(false); _logger.LogInformation("Begin iterate in collection of aggregate."); foreach (var aggregate in _aggregates) { _logger.LogInformation($"Checking if should take snapshot for aggregate: '{aggregate.Id}'."); if (_snapshotStrategy.ShouldMakeSnapshot(aggregate)) { _logger.LogInformation("Taking aggregate's snapshot."); await aggregate.TakeSnapshot(_snapshotStore).ConfigureAwait(false); } _logger.LogInformation($"Update aggregate's version from {aggregate.Version} to {aggregate.Sequence}."); aggregate.UpdateVersion(aggregate.Sequence); aggregate.ClearUncommittedEvents(); } _logger.Log(LogLevel.Information, "End iterate."); _logger.LogInformation($"Publishing events. [Qty: {uncommittedEvents.Count}]"); await _eventPublisher.PublishAsync(uncommittedEvents.Select(e => e.EventWrapper)).ConfigureAwait(false); _logger.LogInformation("Published events."); //ResetTracking(); await _eventPublisher.CommitAsync().ConfigureAwait(false); } catch (Exception e) { _logger.Log(LogLevel.Error, e.Message, e); if (!_externalTransaction) { Rollback(); } throw; } if (!_externalTransaction) { await CommitAsync().ConfigureAwait(false); } }
/// <summary> /// Call <see cref="IEventStore.SaveAsync"/> in <see cref="IEventStore"/> passing serialized events. /// </summary> public virtual async Task SaveChangesAsync() { _logger.LogInformation($"Called method: {nameof(Session)}.{nameof(SaveChangesAsync)}."); if (!_externalTransaction) { _eventStore.BeginTransaction(); } // If transaction called externally, the client should care with transaction. try { _logger.LogInformation("Serializing events."); var uncommitedEvents = _aggregates.SelectMany(e => e.UncommitedEvents) .OrderBy(o => o.CreatedAt) .Cast <UncommitedEvent>() .ToList(); var serializedEvents = new Collection <ISerializedEvent>(); foreach (var uncommitedEvent in uncommitedEvents) { var metadatas = _metadataProviders.SelectMany(md => md.Provide(uncommitedEvent.Aggregate, uncommitedEvent.OriginalEvent, Metadata.Empty)).Concat(new[] { new KeyValuePair <string, object>(MetadataKeys.EventId, Guid.NewGuid()), new KeyValuePair <string, object>(MetadataKeys.EventVersion, uncommitedEvent.Version), new KeyValuePair <string, object>(MetadataKeys.Timestamp, DateTime.UtcNow), }); var metadata = new Metadata(metadatas); var serializeEvent = _eventSerializer.Serialize(uncommitedEvent.Aggregate, uncommitedEvent.OriginalEvent, metadata); serializedEvents.Add(serializeEvent); _eventsMetadataService.Add(uncommitedEvent.OriginalEvent, metadata); } _logger.LogInformation("Saving events on Event Store."); await _eventStore.SaveAsync(serializedEvents).ConfigureAwait(false); _logger.LogInformation("Begin iterate in collection of aggregate."); foreach (var aggregate in _aggregates) { _logger.LogInformation($"Checking if should take snapshot for aggregate: '{aggregate.Id}'."); if (_snapshotStrategy.ShouldMakeSnapshot(aggregate)) { _logger.LogInformation("Taking aggregate's snapshot."); await aggregate.TakeSnapshot(_eventStore, _snapshotSerializer).ConfigureAwait(false); } _logger.LogInformation($"Update aggregate's version from {aggregate.Version} to {aggregate.Sequence}."); aggregate.UpdateVersion(aggregate.Sequence); aggregate.ClearUncommitedEvents(); _logger.LogInformation($"Scanning projection providers for {aggregate.GetType().Name}."); var scanResult = await _projectionProviderScanner.ScanAsync(aggregate.GetType()).ConfigureAwait(false); _logger.LogInformation($"Projection providers found: {scanResult.Providers.Count()}."); foreach (var provider in scanResult.Providers) { var projection = provider.CreateProjection(aggregate); var projectionSerialized = _projectionSerializer.Serialize(aggregate.Id, projection); await _eventStore.SaveProjectionAsync(projectionSerialized).ConfigureAwait(false); } } _logger.Log(LogLevel.Information, "End iterate."); _logger.LogInformation($"Publishing events. [Qty: {uncommitedEvents.Count}]"); await _eventPublisher.PublishAsync(uncommitedEvents.Select(e => e.OriginalEvent)).ConfigureAwait(false); _logger.LogInformation("Published events."); //ResetTracking(); await _eventPublisher.CommitAsync().ConfigureAwait(false); } catch (Exception e) { _logger.Log(LogLevel.Error, e.Message, e); if (!_externalTransaction) { Rollback(); } throw; } if (!_externalTransaction) { await CommitAsync().ConfigureAwait(false); } }
/// <summary> /// Call <see cref="IEventStore.SaveAsync"/> in <see cref="IEventStore"/> passing serialized events. /// </summary> public virtual async Task CommitAsync() { _logger.LogInformation($"Called method: {nameof(Session)}.{nameof(CommitAsync)}."); var aggregatesWithCommits = Aggregates.Where(x => x.UncommitedEvents.Count > 0).ToList(); AssertNoDuplicateCommits(aggregatesWithCommits); if (!_transactionStarted) { _eventStore.BeginTransaction(); } try { _logger.LogDebug("Serializing events."); var uncommitedEvents = aggregatesWithCommits.SelectMany(e => e.UncommitedEvents) .OrderBy(o => o.CreatedAt) .Cast <UncommitedEvent>() .ToList(); var serializedEvents = uncommitedEvents.Select(uncommitedEvent => { var metadata = _metadataProviders.SelectMany(md => md.Provide(uncommitedEvent.Aggregate, uncommitedEvent.OriginalEvent, Metadata.Empty)).Concat(new[] { new KeyValuePair <string, object>(MetadataKeys.EventId, Guid.NewGuid()), new KeyValuePair <string, object>(MetadataKeys.EventVersion, uncommitedEvent.Version) }); var serializedEvent = _eventSerializer.Serialize(uncommitedEvent.OriginalEvent, metadata); return(serializedEvent); }).ToList(); _logger.LogDebug("Saving events on Event Store."); await _eventStore.SaveAsync(serializedEvents).ConfigureAwait(false); _logger.LogDebug("Begin iterate in collection of stream."); foreach (var aggregate in _aggregateTracker.Aggregates) { _logger.LogDebug($"Update stream's version from {aggregate.Version} to {aggregate.UncommittedVersion}."); aggregate.SetVersion(aggregate.UncommittedVersion); aggregate.ClearUncommitedEvents(); _logger.LogDebug($"Scanning projection providers for {aggregate.GetType().Name}."); } _logger.LogInformation($"Publishing events. [Qty: {uncommitedEvents.Count}]"); await _eventPublisher.EnqueueAsync(uncommitedEvents.Select(e => e.OriginalEvent)).ConfigureAwait(false); _logger.LogDebug("Published events."); _aggregateTracker.Clear(); _logger.LogDebug($"Calling method: {_eventStore.GetType().Name}.{nameof(CommitAsync)}."); await _eventStore.CommitAsync().ConfigureAwait(false); _transactionStarted = false; await _eventPublisher.CommitAsync().ConfigureAwait(false); } catch (Exception e) { _logger.LogError(e.Message, e); Rollback(); throw; } }