internal TestUnitOfWork(IAggregateRootRepository aggregateRootRepository, IEventStore eventStore, IEventDispatcher eventDispatcher, IDomainEventSerializer domainEventSerializer, IDomainTypeNameMapper domainTypeNameMapper)
 {
     _eventStore            = eventStore;
     _eventDispatcher       = eventDispatcher;
     _domainEventSerializer = domainEventSerializer;
     _realUnitOfWork        = new RealUnitOfWork(aggregateRootRepository, domainTypeNameMapper);
 }
 /// <summary>
 /// Creates the view context with the given repository and type name mapper, storing the given event batch to be able to look up events in case it could make sense
 /// </summary>
 public DefaultViewContext(IAggregateRootRepository aggregateRootRepository, IDomainTypeNameMapper domainTypeNameMapper, IEnumerable <DomainEvent> eventBatch)
 {
     Items = new Dictionary <string, object>();
     _aggregateRootRepository = aggregateRootRepository;
     _eventBatch     = eventBatch.OrderBy(e => e.GetGlobalSequenceNumber()).ToList();
     _realUnitOfWork = new RealUnitOfWork(_aggregateRootRepository, domainTypeNameMapper);
 }
            public void MaybeApply(DomainEvent domainEvent, RealUnitOfWork realUnitOfWork, long requestedGlobalSequenceNumber)
            {
                // other roots' events are not relevant
                if (domainEvent.GetAggregateRootId() != _aggregateRootInfo.Id)
                {
                    return;
                }

                var globalSequenceNumberFromEvent = domainEvent.GetGlobalSequenceNumber();

                // don't do anything if we are not supposed to go this far
                if (globalSequenceNumberFromEvent > requestedGlobalSequenceNumber)
                {
                    return;
                }

                // don't do anything if the event is in the past
                if (globalSequenceNumberFromEvent <= _globalSequenceNumber)
                {
                    return;
                }

                // if this entry is a future version of the requested version, it's not ok.... sorry!
                if (_globalSequenceNumber > requestedGlobalSequenceNumber)
                {
                    IsOk = false;
                    return;
                }

                try
                {
                    var sequenceNumberFromEvent    = domainEvent.GetSequenceNumber();
                    var expectedNextSequenceNumber = _aggregateRootInfo.SequenceNumber + 1;

                    if (expectedNextSequenceNumber != sequenceNumberFromEvent)
                    {
                        IsOk = false;
                        return;
                    }

                    _aggregateRootInfo.Apply(domainEvent, realUnitOfWork);

                    _globalSequenceNumber = globalSequenceNumberFromEvent;
                }
                catch (Exception exception)
                {
                    _logger.Warn(exception, "Got an error while bringing cache entry for {0} up-to-date to {1}",
                                 _aggregateRootInfo.Id, requestedGlobalSequenceNumber);

                    IsOk = false;
                }
            }
Esempio n. 4
0
        IEnumerable <DomainEvent> InnerProcessCommand(RealUnitOfWork unitOfWork, Command command)
        {
            var handler = _commandMapper.GetCommandAction(command);

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

            var emittedEvents = unitOfWork.EmittedEvents.ToList();

            if (!emittedEvents.Any())
            {
                return(emittedEvents);
            }

            return(emittedEvents);
        }
Esempio n. 5
0
        IEnumerable <DomainEvent> InnerProcessCommand(Command command)
        {
            var unitOfWork = new RealUnitOfWork(_aggregateRootRepository, _domainTypeNameMapper);

            var handler = _commandMapper.GetCommandAction(command);

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

            var emittedEvents = unitOfWork.EmittedEvents.ToList();

            if (!emittedEvents.Any())
            {
                return(emittedEvents);
            }

            return(emittedEvents);
        }
Esempio n. 6
0
        public void CheckHydrationPerformance(int historyLength, bool useCaching)
        {
            var aggregateRootId = Guid.NewGuid();

            GeneratePrettyLongHistory(aggregateRootId, historyLength);

            TakeTime("Load instance", () =>
            {
                100.Times(() =>
                {
                    var realUnitOfWork = new RealUnitOfWork(_cachingAggregateRootRepository, _domainTypeNameMapper);

                    if (useCaching)
                    {
                        _cachingAggregateRootRepository.Get <Root>(aggregateRootId.ToString(), realUnitOfWork);
                    }
                    else
                    {
                        _realAggregateRootRepository.Get <Root>(aggregateRootId.ToString(), realUnitOfWork);
                    }
                });
            });
        }
        /// <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. 8
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();
        }
 public FrozenAggregateRootService(AggregateRoot aggregateRootInfo, RealUnitOfWork realUnitOfWork)
 {
     _aggregateRootInfo = aggregateRootInfo;
     _realUnitOfWork    = realUnitOfWork;
 }
Esempio n. 10
0
        public DefaultViewContext(IAggregateRootRepository aggregateRootRepository, IDomainTypeNameMapper domainTypeNameMapper)
        {
            _aggregateRootRepository = aggregateRootRepository;

            _realUnitOfWork = new RealUnitOfWork(_aggregateRootRepository, domainTypeNameMapper);
        }
Esempio n. 11
0
        IEnumerable<DomainEvent> InnerProcessCommand(RealUnitOfWork unitOfWork, Command command)
        {
            var handler = _commandMapper.GetCommandAction(command);

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

            var emittedEvents = unitOfWork.EmittedEvents.ToList();

            if (!emittedEvents.Any()) return emittedEvents;

            return emittedEvents;
        }