/// <summary>
        /// Processes the specified command by invoking the generic eventDispatcher method
        /// </summary>
        public CommandProcessingResult ProcessCommand(Command command)
        {
            _logger.Debug("Processing command: {0}", command);

            var emittedDomainEvents = new List <DomainEvent>();

            try
            {
                var batchId = Guid.NewGuid();

                _retryer.RetryOn <ConcurrencyException>(() =>
                {
                    var unitOfWork = new RealUnitOfWork(_aggregateRootRepository, _domainTypeNameMapper);
                    var handler    = _commandMapper.GetCommandAction(command);

                    handler(new DefaultCommandContext(unitOfWork, command.Meta), command);

                    var eventsFromThisUnitOfWork = unitOfWork.EmittedEvents.ToList();

                    // if command processing yielded no events, there's no more work to do
                    if (!eventsFromThisUnitOfWork.Any())
                    {
                        return;
                    }

                    // first: save the events
                    _logger.Debug("Saving batch {0} with {1} events", batchId, eventsFromThisUnitOfWork.Count);

                    var eventData = eventsFromThisUnitOfWork.Select(e => _domainEventSerializer.Serialize(e)).ToList();

                    _eventStore.Save(batchId, eventData);

                    unitOfWork.RaiseCommitted(eventsFromThisUnitOfWork);

                    emittedDomainEvents.AddRange(eventsFromThisUnitOfWork);
                }, maxRetries: Options.MaxRetries);
            }
            catch (Exception exception)
            {
                // ordinary re-throw if exception is a domain exception
                if (Options.DomainExceptionTypes.Contains(exception.GetType()))
                {
                    throw;
                }

                throw CommandProcessingException.Create(command, exception);
            }

            try
            {
                _logger.Debug("Delivering {0} events to the dispatcher", emittedDomainEvents.Count);

                // when we come to this place, we deliver the events to the view manager
                _eventDispatcher.Dispatch(emittedDomainEvents);
            }
            catch (Exception exception)
            {
                var message =
                    string.Format(
                        "An error ocurred while dispatching events with global sequence numbers {0} to event dispatcher." +
                        " The events were properly saved in the event store, but you might need to re-initialize the" +
                        " event dispatcher",
                        string.Join(", ", emittedDomainEvents.Select(e => e.GetGlobalSequenceNumber())));

                throw new ApplicationException(message, exception);
            }

            return(emittedDomainEvents.Any()
                ? CommandProcessingResult.WithNewPosition(emittedDomainEvents.Max(e => e.GetGlobalSequenceNumber()))
                : CommandProcessingResult.NoEvents());
        }
Esempio n. 2
0
        /// <summary>
        /// Processes the specified command by invoking the generic eventDispatcher method
        /// </summary>
        public CommandProcessingResult ProcessCommand(Command command)
        {
            _logger.Debug("Processing command: {0}", command);

            var emittedDomainEvents = new List<DomainEvent>();

            try
            {
                var batchId = Guid.NewGuid();

                _retryer.RetryOn<ConcurrencyException>(() =>
                {
                    var unitOfWork = new RealUnitOfWork(_aggregateRootRepository, _domainTypeNameMapper);
                    var handler = _commandMapper.GetCommandAction(command);

                    handler(new DefaultCommandContext(unitOfWork, command.Meta), command);

                    var eventsFromThisUnitOfWork = unitOfWork.EmittedEvents.ToList();

                    // if command processing yielded no events, there's no more work to do
                    if (!eventsFromThisUnitOfWork.Any()) return;

                    // first: save the events
                    _logger.Debug("Saving batch {0} with {1} events", batchId, eventsFromThisUnitOfWork.Count);

                    var eventData = eventsFromThisUnitOfWork.Select(e => _domainEventSerializer.Serialize(e)).ToList();

                    _eventStore.Save(batchId, eventData);

                    unitOfWork.RaiseCommitted(eventsFromThisUnitOfWork);

                    emittedDomainEvents.AddRange(eventsFromThisUnitOfWork);

                }, maxRetries: Options.MaxRetries);
            }
            catch (Exception exception)
            {
                // ordinary re-throw if exception is a domain exception
                if (Options.DomainExceptionTypes.Contains(exception.GetType()))
                {
                    throw;
                }

                throw CommandProcessingException.Create(command, exception);
            }

            try
            {
                _logger.Debug("Delivering {0} events to the dispatcher", emittedDomainEvents.Count);

                // when we come to this place, we deliver the events to the view manager
                _eventDispatcher.Dispatch(emittedDomainEvents);
            }
            catch (Exception exception)
            {
                var message =
                    string.Format(
                        "An error ocurred while dispatching events with global sequence numbers {0} to event dispatcher." +
                        " The events were properly saved in the event store, but you might need to re-initialize the" +
                        " event dispatcher",
                        string.Join(", ", emittedDomainEvents.Select(e => e.GetGlobalSequenceNumber())));

                throw new ApplicationException(message, exception);
            }

            return emittedDomainEvents.Any()
                ? CommandProcessingResult.WithNewPosition(emittedDomainEvents.Max(e => e.GetGlobalSequenceNumber()))
                : CommandProcessingResult.NoEvents();
        }