Ejemplo n.º 1
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);
            }
        }
Ejemplo n.º 2
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);
            }
        }