Beispiel #1
0
        /// <summary>
        /// Gets aggregate root by its id.
        /// </summary>
        /// <param name="aggregateRootType">Type of the aggregate root.</param>
        /// <param name="eventSourceId">The eventSourceId of the aggregate root.</param>
        /// <param name="lastKnownRevision">If specified, the most recent version of event source observed by the client (used for optimistic concurrency).</param>
        /// <returns>
        /// A new instance of the aggregate root that contains the latest known state.
        /// </returns>
        public override AggregateRoot GetById(Type aggregateRootType, Guid eventSourceId, long?lastKnownRevision)
        {
            long     maxVersion = lastKnownRevision.HasValue ? lastKnownRevision.Value : long.MaxValue;
            Snapshot snapshot   = null;
            long     minVersion = long.MinValue;

            snapshot = _snapshotStore.GetSnapshot(eventSourceId, maxVersion);
            if (snapshot != null)
            {
                minVersion = snapshot.Version + 1;
            }
            var eventStream = _eventStore.ReadFrom(eventSourceId, minVersion, maxVersion);

            return(_repository.Load(aggregateRootType, snapshot, eventStream));
        }
Beispiel #2
0
        /// <summary>
        /// Returns <c>true</c> if a snapshould should be created
        /// </summary>
        /// <param name="aggregateId">The Id of an aggregate</param>
        /// <param name="aggregateType">The type of an aggregate</param>
        /// <param name="aggregateVersion">The current version of the aggregate</param>
        /// <returns><c>True</c> if a snapshould should be created</returns>
        public bool IsSnapshotNeeded(Guid aggregateId, Type aggregateType, int aggregateVersion)
        {
            //Check if snapshotting is supported
            if (!_repositories.ContainsKey(aggregateType) && aggregateVersion == 0)
            {
                return(false);
            }

            var snapshot    = _snapshotStore.GetSnapshot(aggregateId);
            var lastVersion = snapshot?.Version ?? 0;

            return(aggregateVersion - lastVersion >= _snapshotThreshold);

            //return aggregateVersion % _snapshotThreshold == 0;
        }
Beispiel #3
0
        public async Task Load(TAggregate aggregate, long?toVersion = null)
        {
            int maxCount = toVersion.HasValue ? (int)(toVersion.Value - aggregate.Version) : int.MaxValue;

            var snapshot = await _snapShotStore.GetSnapshot <TState>(aggregate.GetId());

            if (snapshot != null && snapshot.AggregateVersion < toVersion)
            {
                aggregate.ApplySnapshot(snapshot);
            }

            var events = await _eventStore.GetAggregateEvents <TAggregate, TState>(aggregate.GetId(), aggregate.Version + 1, maxCount);

            foreach (var @event in events)
            {
                aggregate.ApplyEvent(@event);
            }
        }
        private async Task ApplyLatestSnapshot <T>(T domainObject, string identifier, long maxVersion, string cacheKey)
            where T : DomainObject
        {
            _logger.LogDebug($"no cached item for key '{cacheKey}' found, attempting to " +
                             $"retrieve latest snapshot below or at version {maxVersion} for '{identifier}'");

            var latestSnapshot = await _snapshotStore.GetSnapshot <T>(identifier, maxVersion);

            if (latestSnapshot.IsError)
            {
                return;
            }

            _logger.LogDebug($"snapshot for '{identifier}' found, " +
                             $"version '{latestSnapshot.Data.Version}', " +
                             $"meta '{latestSnapshot.Data.MetaVersion}'");

            domainObject.ApplySnapshot(latestSnapshot.Data);
        }
Beispiel #5
0
        protected SnapResult Snap(SnapshotId snapshotId, object newSnapshot)
        {
            var currentSnapshot = _snapshotStore.GetSnapshot(snapshotId);

            if (ShouldUpdateSnapshot(currentSnapshot, newSnapshot))
            {
                _snapshotStore.StoreSnapshot(snapshotId, newSnapshot);
                return(SnapResult.SnapshotUpdated(currentSnapshot, newSnapshot));
            }

            if (currentSnapshot == null)
            {
                return(SnapResult.SnapshotDoesNotExist(newSnapshot));
            }

            return(_snapshotComparer.CompareSnapshots(currentSnapshot, newSnapshot)
                ? SnapResult.SnapshotsMatch(currentSnapshot, newSnapshot)
                : SnapResult.SnapshotsDoNotMatch(currentSnapshot, newSnapshot));
        }
Beispiel #6
0
        /// <summary>
        /// Returns the aggregate with the given <paramref name="id"/> or creates a new one.
        /// </summary>
        /// <param name="id">The id of the aggregate</param>
        /// <returns>Current state of the aggregate</returns>
        public TAggregate GetById(Guid id)
        {
            var snapshot = IsSnapshotSupported() ? _snapshotStore.GetSnapshot(id) : null;

            var events = snapshot != null
                ? _eventStore.GetEventsByAggregateId(id, snapshot.Version)
                : _eventStore.GetEventsByAggregateId(id);

            var aggregate = new TAggregate();

            if (snapshot != null)
            {
                ((ISnapshotOriginator)aggregate).SetSnapshot(snapshot);
            }

            aggregate.LoadFromHistory(events);

            return(aggregate);
        }
        public void Handle(EntityUpdatedEvent message)
        {
            if (!_budgetModel.IsSavingLocally)
            {
                var     snapshot = _snapshotStore.GetSnapshot <TSnapshot>(message.EntityID);
                TEntity entity;
                if (snapshot != null)
                {
                    entity = _createEntityFromSnapshot(snapshot);
                }
                else
                {
                    entity = _repository.MaterializeNewEntityCopy(message.EntityID);
                }

                entity.ReplayEvents(message.Yield());
                snapshot = entity.GetSnapshot();
                _snapshotStore.StoreSnapshot(snapshot);
            }
        }
Beispiel #8
0
        /// <summary>
        /// Gets aggregate root by eventSourceId. If aggregate root with this id does not exist, returns null.
        /// </summary>
        /// <param name="aggregateRootType">Type of the aggregate root.</param>
        /// <param name="eventSourceId">The eventSourceId of the aggregate root.</param>
        /// <returns>A new instance of the aggregate root that contains the latest known state or null</returns>
        public AggregateRoot TryGetById(Type aggregateRootType, Guid eventSourceId)
        {
            AggregateRoot aggregate = null;

            if (_snapshotStore != null)
            {
                var snapshot = _snapshotStore.GetSnapshot(eventSourceId);

                if (snapshot != null)
                {
                    aggregate = GetByIdFromSnapshot(aggregateRootType, snapshot);
                }
            }

            if (aggregate == null)
            {
                aggregate = GetByIdFromScratch(aggregateRootType, eventSourceId);
            }
            return(aggregate);
        }
Beispiel #9
0
        private async Task <IAggregateRoot> LoadAggregate(ICommand command)
        {
            var aggregate = _factory.Build(command.Destination);

            if (aggregate is ISupportSnapshots withSnapshots)
            {
                var snapshot = await _snapshotStore.GetSnapshot(command.Destination);

                if (snapshot != null)
                {
                    aggregate = withSnapshots.RestoreFromSnapshot(snapshot);
                }
            }

            await foreach (var e in _eventStore.GetEventStream(aggregate.Address))
            {
                aggregate.Apply(e);
            }

            return(aggregate);
        }
Beispiel #10
0
        protected SnapResult Snap(SnapshotId snapshotId, object newSnapshot)
        {
            var currentSnapshot   = _snapshotStore.GetSnapshot(snapshotId);
            var areSnapshotsEqual = currentSnapshot != null &&
                                    _snapshotComparer.CompareSnapshots(currentSnapshot, newSnapshot);

            if (!areSnapshotsEqual && _snapshotUpdateDecider.ShouldUpdateSnapshot())
            {
                _snapshotStore.StoreSnapshot(snapshotId, newSnapshot);
                return(SnapResult.SnapshotUpdated(currentSnapshot, newSnapshot));
            }

            if (currentSnapshot == null)
            {
                return(SnapResult.SnapshotDoesNotExist(newSnapshot));
            }

            return(areSnapshotsEqual
                ? SnapResult.SnapshotsMatch(currentSnapshot, newSnapshot)
                : SnapResult.SnapshotsDoNotMatch(currentSnapshot, newSnapshot));
        }
        public TEntity GetEntity(string entityId)
        {
            var snapshot = _snapshotStore.GetSnapshot <TSnapshot>(entityId);

            if (snapshot != null)
            {
                return(LoadEntityFromSnapshot(snapshot));
            }
            else
            {
                if (IsValidID(entityId))
                {
                    TEntity entity = MaterializeEntity(entityId);
                    _budgetModel.AttachToModel(entity);
                    entity.LoadSubEntities();
                    return(entity);
                }
                else
                {
                    return(null);
                }
            }
        }
Beispiel #12
0
 private Snapshot GetSnapshotFromSnapshotStore(Guid aggregateRootId)
 {
     return(snapshotStore.GetSnapshot(aggregateRootId) ?? new Snapshot());
 }
Beispiel #13
0
        public Bundle GetPage(string snapshotkey, int start = 0, int count = DEFAULT_PAGE_SIZE)
        {
            Snapshot snapshot = snapshotstore.GetSnapshot(snapshotkey);

            return(GetPage(snapshot, start, count));
        }
Beispiel #14
0
 public async Task <ISnapshotPagination> StartPagination(string snapshotkey) =>
 _snapshotstore == null
         ? throw new NotSupportedException("Stateful pagination is not currently supported.")
         : _paginationProvider.StartPagination(
           await _snapshotstore.GetSnapshot(snapshotkey).ConfigureAwait(false));
Beispiel #15
0
        public Bundle GetPage(string snapshotkey, int start)
        {
            Snapshot snapshot = snapshotstore.GetSnapshot(snapshotkey);

            return(GetPage(snapshot, start));
        }