public CachedRoot(object aggregateRoot, long globalSequenceNumber)
 {
     AggregateRoot         = aggregateRoot;
     IsOk                  = true;
     _globalSequenceNumber = globalSequenceNumber;
     _aggregateRootInfo    = new AggregateRootInfo(aggregateRoot as AggregateRoot);
 }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #5
0
        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);
            };
        }