AggregateRoot PrepareFromSnapshot <TAggregateRoot>(Snapshot matchingSnapshot, long maxGlobalSequenceNumber, IUnitOfWork unitOfWork, string aggregateRootId) { var instance = matchingSnapshot.Instance; var hadEventsAppliedToIt = false; var stopwatch = Stopwatch.StartNew(); if (matchingSnapshot.ValidFromGlobalSequenceNumber < maxGlobalSequenceNumber) { var info = new AggregateRootInfo(instance); foreach (var e in _eventStore.Load(aggregateRootId, info.SequenceNumber + 1)) { if (e.GetGlobalSequenceNumber() > maxGlobalSequenceNumber) { break; } var domainEvent = _domainEventSerializer.Deserialize(e); info.Apply(domainEvent, unitOfWork); hadEventsAppliedToIt = true; } info.SetUnitOfWork(unitOfWork); } if (hadEventsAppliedToIt && stopwatch.Elapsed > _preparationThreshold) { _snapshotStore.SaveSnapshot <TAggregateRoot>(aggregateRootId, instance, maxGlobalSequenceNumber); } return(instance); }
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; } }