Beispiel #1
0
        /// <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);
            }
        }
Beispiel #2
0
        /// <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);
            }
        }
Beispiel #3
0
        /// <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);
            }
        }
Beispiel #4
0
        /// <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;
            }
        }