public async ValueTask <RepositoryEntityState> PreSaveChangesAsync(RepositoryEntityState entityState, object entity, CancellationToken cancellationToken = default)
        {
            if (entity is IDomainEventProvider domainEventProvider)
            {
                var entityEvents        = domainEventProvider.GetDomainEvents();
                var completedEventCount = 0;

                if (entityEvents == null || entityEvents.Count == 0)
                {
                    return(entityState);
                }

                foreach (var @event in entityEvents)
                {
                    try
                    {
                        await _eventDispatcher.DispatchAsync(@event);

                        completedEventCount++;
                    }
                    catch (Exception ex)
                    {
                        _logger.LogWarning(ex, "There has a error when dispatch domain event.");
                    }
                }

                if (completedEventCount != entityEvents.Count)
                {
                    //count is not equal. prove the existence of failed events
                }
            }
            return(entityState);
        }
Ejemplo n.º 2
0
        private async Task DispatchEventsToBeProcessed(CancellationToken cancellationToken)
        {
            var eventId = Guid.Empty;

            try
            {
                _logger.Debug("About to dispatch EventsToBeProcessed...");
                foreach (var @event in _eventBag.EventsToBeProcessed.ToList())
                {
                    eventId = @event.Id;
                    _logger.Debug($"Publishing event. Id: {@event.Id} SourceType: {@event.SourceTypeName}");
                    await _eventDispatcher.DispatchAsync(@event, cancellationToken);

                    _eventBag.EventsToBeProcessed.Remove(@event);

                    if (_cqrsOptions.PurgeEventsToBeProcessed)
                    {
                        await PurgeEvent(@event, cancellationToken);
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.Error($"Dispatching failed. Id: {eventId}");
                _logger.Error(ex);
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Asynchronously processes an event queue by dispatching the events
        /// </summary>
        /// <param name="preTransaction">True, if pre-transaction handlers required</param>
        /// <param name="queue">The event queue to process</param>
        private async Task ProcessEventQueue(IEventQueue queue, bool preTransaction = false)
        {
            var queueTasks = new List <Task>();

            while (false == queue.IsEmpty())
            {
                var nextItem     = queue.GetNext();
                var dispatchTask = _eventDispatcher.DispatchAsync(nextItem.Event, preTransaction);

                queueTasks.Add(dispatchTask);

                // We don't want to log pre-transaction events
                if (false == preTransaction)
                {
                    var logTask = _eventLogger.LogEventAsync
                                  (
                        nextItem.AggregateKey,
                        nextItem.AggregateType,
                        nextItem.Event
                                  );

                    queueTasks.Add(logTask);
                }
            }

            await Task.WhenAll(queueTasks).ConfigureAwait(false);
        }
        public async Task <TEvent> DispatchAsync <TEvent>(ICommand <TEvent> command, CancellationToken cancellationToken)
            where TEvent : IEvent
        {
            var commandHandlerType = s_commandHandlerGenericType.MakeGenericType(command.GetType(), typeof(TEvent));
            var handleMethod       = commandHandlerType.GetTypeInfo().GetMethod("HandleAsync");
            var commandHandler     = _componentContext.Resolve(commandHandlerType);

            TEvent @event;

            @event = await(dynamic) handleMethod.Invoke(commandHandler, new object[] { command, cancellationToken });

            try
            {
                await _eventDispatcher.DispatchAsync(@event, cancellationToken);
            }
            catch (Exception exception)
            {
                var eventName     = @event.GetType().FullName;
                var exceptionName = exception.GetType().FullName;

                _logger.LogError
                (
                    new EventId(),
                    exception,
                    "Exception {ExceptionName} thrown with message {ExceptionMessage} when handling event {EventName}",
                    exceptionName,
                    exception.Message,
                    eventName
                );
            }

            return(@event);
        }
Ejemplo n.º 5
0
        public async Task CreateAsync(string email)
        {
            var user = new User(email);
            //Store the user somehwere safe using the repository etc.

            //Dispatch all of the user events
            await _eventDispatcher.DispatchAsync(user.Events.ToArray());
        }
 private async Task DispatchEvents()
 {
     var entities = ChangeTracker
                    .Entries <Entity>()
                    .Where(x => x.Entity.DomainEvents != null && x.Entity.DomainEvents.Any())
                    .Select(x => x.Entity);
     await eventDispatcher.DispatchAsync(entities);
 }
Ejemplo n.º 7
0
        public override async Task <int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
        {
            var affectedRows = await base.SaveChangesAsync(cancellationToken);

            await _eventDispatcher.DispatchAsync(this);

            return(affectedRows);
        }
Ejemplo n.º 8
0
        public async Task CreateAsync(string email)
        {
            var user = new User(email);

            // store

            await _eventDispatcher.DispatchAsync(user.Events.ToArray());
        }
Ejemplo n.º 9
0
        public async Task SignUpAsync(Guid id, string email, string password, string role)
        {
            var user = await _userFactory.CreateAsync(id, email, password, role);

            await _userRepository.CreateAsync(user);

            await _eventDispatcher.DispatchAsync(user.Events.ToArray());
        }
 private async Task DispatchEventsAsync(CancellationToken cancellationToken = default)
 {
     var entities = ChangeTracker
                    .Entries <EntityBase>()
                    .Where(x => x.Entity.DomainEvents != null && x.Entity.DomainEvents.Any())
                    .Select(x => x.Entity);
     await _eventDispatcher.DispatchAsync(entities, cancellationToken);
 }
Ejemplo n.º 11
0
        public async Task <IEventSourcedAggregate <TAggregate> > RetrieveAsync(Guid id)
        {
            var eventList = await _eventRepository.RetriveEventsAsync <TAggregate>(id);

            var aggregate = new RecordedAggregate <TAggregate>(id, eventList.AggregateVersion, eventList.DomainEvents, this, _eventDispatcher);

            foreach (var @event in eventList.DomainEvents)
            {
                await _eventDispatcher.DispatchAsync(aggregate.State, @event);
            }
            return(aggregate);
        }
Ejemplo n.º 12
0
        private async Task DispatchDomainEvents()
        {
            var domainEventEntities = ChangeTracker.Entries <IAggregateRoot>()
                                      .Select(po => po.Entity)
                                      .Where(po => po.Events.Any())
                                      .ToArray();

            foreach (var entity in domainEventEntities)
            {
                foreach (var @event in entity.Events)
                {
                    await _eventDispatcher.DispatchAsync(@event);
                }
            }
        }
Ejemplo n.º 13
0
        public async Task ProcessAsync <TCommand>(TCommand command) where TCommand : CommandBase
        {
            foreach (var commandHandler in _commandHandlers.Where(e => e.GetCommandType() == command.GetType()))
            {
                var aggregate = await commandHandler.UpdatedAggregateAsync(command);

                if (aggregate != null)
                {
                    var newEvents = aggregate.UncommittedEvents;
                    await _aggregateRepo.AddOrUpdateAsync(aggregate);

                    await _eventDispatcher.DispatchAsync(newEvents);
                }
            }
        }
Ejemplo n.º 14
0
        public ISubscriber SubscribeEvent <TEvent>(string @namespace = null, string queueName = null,
                                                   Func <TEvent, MiddlinkException, IRejectedEvent> onError = null)
            where TEvent : IDomainEvent
        {
            _busClient.SubscribeAsync <TEvent>((@event, correlationContext) =>
            {
                return(TryHandleAsync(@event, correlationContext,
                                      () =>
                {
                    IEventDispatcher dispatcher = _appServiceProvider.CreateScope().ServiceProvider.GetService <IEventDispatcher>();
                    return dispatcher.DispatchAsync(@event, correlationContext);
                }, onError));
            }, @namespace);

            return(this);
        }
Ejemplo n.º 15
0
        public Task HandleAsync(
            ICommandHandlingContext <LogInUser> context,
            CancellationToken cancellationToken = default)
        {
            ExecutionContext.CurrentUser = new User
            {
                Name       = context.Command.Name,
                LoggedInAt = DateTime.Now
            };

            _eventDispatcher.DispatchAsync(new UserWasLoggedIn(
                                               ExecutionContext.CurrentUser.Name,
                                               ExecutionContext.CurrentUser.LoggedInAt),
                                           cancellationToken);

            return(Task.CompletedTask);
        }
Ejemplo n.º 16
0
        public async Task <ProductOut> DeleteByIdAsync(Guid productId)
        {
            productId.NotNullOrDefault(nameof(productId));
            var product = await _productRepository.GetAsync(productId);

            if (product != null)
            {
                await _productRepository.DeleteAsync(product);

                await _eventDispatcher.DispatchAsync(new ProductDeletedEvent(productId));

                return(_mapper.Map <ProductOut>(product));
            }
            else
            {
                throw new MSFrameworkException(110, "Product is not exists");
            }
        }
Ejemplo n.º 17
0
        public async Task StartAsync(CancellationToken cancellationToken)
        {
            var       streamName = RedisExtensions.GetPrimaryStream();
            IDatabase db         = _connectionMultiplexer.GetDatabase();
            var       batchSize  = _configuration.BatchSize;

            while (true)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }
                var checkpoint = await _checkPoint.GetCheckpoint <T>();

                var streamInfo = db.StreamInfo(streamName);
                if (streamInfo.LastEntry.Id == checkpoint)
                {
                    await Task.Delay(_configuration.Delay, cancellationToken);

                    continue;
                }

                var currentSlice = await db.StreamReadAsync(streamName, checkpoint, batchSize);

                foreach (var streamEntry in currentSlice)
                {
                    foreach (var streamEntryValue in streamEntry.Values)
                    {
                        var @event = JsonConvert.DeserializeObject <AggregateEvent>(streamEntryValue.Value.ToString(), _serializerSettings);
                        await _eventDispatcher.DispatchAsync(@event);

                        await _checkPoint.SetCheckpoint <T>(streamEntry.Id);
                    }
                }
            }
        }
Ejemplo n.º 18
0
        private async Task ProcessDomainEvents(AggregateRoot root)
        {
            await _eventDispatcher.DispatchAsync(root.DomainEvents);

            root.ClearDomainEvents();
        }
Ejemplo n.º 19
0
        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;
            }
        }
Ejemplo n.º 20
0
 public async Task Consume(ConsumeContext <TEvent> context)
 {
     await _eventDispatcher
     .DispatchAsync(context.Message, context.CancellationToken)
     .ConfigureAwait(false);
 }
Ejemplo n.º 21
0
 public async Task DispatchEventAsync(IDomainEvent @event)
 {
     await _eventDispatcher.DispatchAsync(State, @event);
 }