public CachedRoot(object aggregateRoot, long globalSequenceNumber) { AggregateRoot = aggregateRoot; IsOk = true; _globalSequenceNumber = globalSequenceNumber; _aggregateRootInfo = new AggregateRootInfo(aggregateRoot as AggregateRoot); }
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 AggregateRoot Get <TAggregateRoot>(string aggregateRootId, IUnitOfWork unitOfWork, long maxGlobalSequenceNumber = long.MaxValue, bool createIfNotExists = false) { if (!EnabledFor <TAggregateRoot>()) { return(_aggregateRootRepository.Get <TAggregateRoot>(aggregateRootId, unitOfWork, maxGlobalSequenceNumber, createIfNotExists)); } var snapshot = _snapshotStore.LoadSnapshot <TAggregateRoot>(aggregateRootId, maxGlobalSequenceNumber); if (snapshot == null) { var aggregateRootInstance = _aggregateRootRepository.Get <TAggregateRoot>(aggregateRootId, unitOfWork, maxGlobalSequenceNumber, createIfNotExists); var checkedOutSequenceNumber = new AggregateRootInfo(aggregateRootInstance).SequenceNumber; if (maxGlobalSequenceNumber != long.MaxValue) { _snapshotStore.SaveSnapshot <TAggregateRoot>(aggregateRootId, aggregateRootInstance, maxGlobalSequenceNumber); } OnCommitted <TAggregateRoot>(aggregateRootId, unitOfWork, aggregateRootInstance, checkedOutSequenceNumber); return(aggregateRootInstance); } var preparedInstance = PrepareFromSnapshot <TAggregateRoot>(snapshot, maxGlobalSequenceNumber, unitOfWork, aggregateRootId); var sequenceNumberOfPreparedInstance = new AggregateRootInfo(preparedInstance).SequenceNumber; OnCommitted <TAggregateRoot>(aggregateRootId, unitOfWork, preparedInstance, sequenceNumberOfPreparedInstance); return(preparedInstance); }
public void SaveSnapshot <TAggregateRoot>(string aggregateRootId, AggregateRoot aggregateRootInstance, long validFromGlobalSequenceNumber) { var snapshotAttribute = GetSnapshotAttribute(aggregateRootInstance.GetType()); var info = new AggregateRootInfo(aggregateRootInstance); var serializedInstance = _sturdylizer.SerializeObject(info.Instance); _snapshots.Insert(new NewSnapshot { Id = string.Format("{0}/{1}", aggregateRootId, info.SequenceNumber), AggregateRootId = aggregateRootId, Data = serializedInstance, ValidFromGlobalSequenceNumber = validFromGlobalSequenceNumber, Version = snapshotAttribute.Version }, WriteConcern.Unacknowledged); }
void OnCommitted <TAggregateRoot>(string aggregateRootId, IUnitOfWork unitOfWork, AggregateRoot aggregateRootInstance, long checkedOutSequenceNumber) { unitOfWork.Committed += eventBatch => { var aggregateRootHasChanges = new AggregateRootInfo(aggregateRootInstance).SequenceNumber != checkedOutSequenceNumber; if (!aggregateRootHasChanges) { return; } var lastGlobalSequenceNumber = eventBatch.Max(e => e.GetGlobalSequenceNumber()); _snapshotStore.SaveSnapshot <TAggregateRoot>(aggregateRootId, aggregateRootInstance, lastGlobalSequenceNumber); }; }