Beispiel #1
0
        public async Task PublishAsync <TAggregate, TIdentity>(
            TIdentity id,
            IReadOnlyCollection <IDomainEvent> domainEvents,
            CancellationToken cancellationToken)
            where TAggregate : IAggregateRoot <TIdentity>
            where TIdentity : IIdentity
        {
            // ARGH, dilemma, should we pass the cancellation token to read model update or not?
            var updateReadStoresTasks = _readStoreManagers
                                        .Select(rsm => rsm.UpdateReadStoresAsync(domainEvents, CancellationToken.None));
            await Task.WhenAll(updateReadStoresTasks).ConfigureAwait(false);

            // Update subscriptions AFTER read stores have been updated
            await _dispatchToEventSubscribers.DispatchAsync(domainEvents, cancellationToken).ConfigureAwait(false);
        }
Beispiel #2
0
        public async Task PublishAsync <TAggregate>(
            ICommand <TAggregate> command,
            CancellationToken cancellationToken)
            where TAggregate : IAggregateRoot
        {
            if (command == null)
            {
                throw new ArgumentNullException("command");
            }

            var commandType   = command.GetType().Name;
            var aggregateType = typeof(TAggregate);

            _log.Verbose(
                "Executing command '{0}' on aggregate '{1}' with ID '{2}'",
                commandType,
                aggregateType.Name,
                command.Id);

            var domainEvents = await Retry.ThisAsync(
                async() =>
            {
                var aggregate = await _eventStore.LoadAggregateAsync <TAggregate>(command.Id, cancellationToken).ConfigureAwait(false);
                await command.ExecuteAsync(aggregate, cancellationToken).ConfigureAwait(false);
                return(await aggregate.CommitAsync(_eventStore, cancellationToken).ConfigureAwait(false));
            },
                _configuration.NumberOfRetriesOnOptimisticConcurrencyExceptions,
                new [] { typeof(OptimisticConcurrencyException) },
                _configuration.DelayBeforeRetryOnOptimisticConcurrencyExceptions)
                               .ConfigureAwait(false);

            if (!domainEvents.Any())
            {
                _log.Verbose(
                    "Execution command '{0}' on aggregate '{1}' with ID '{2}' did NOT result in any domain events",
                    commandType,
                    aggregateType.Name,
                    command.Id);
                return;
            }

            // TODO: Determine if we can use cancellation token after there, this should be the "point of no return"

            await _readStoreManager.UpdateReadStoresAsync <TAggregate>(command.Id, domainEvents, CancellationToken.None).ConfigureAwait(false);

            await _dispatchToEventSubscribers.DispatchAsync(domainEvents).ConfigureAwait(false);
        }