/// <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)); }
/// <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; }
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); }
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)); }
/// <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); } }
/// <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); }
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); }
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); } } }
private Snapshot GetSnapshotFromSnapshotStore(Guid aggregateRootId) { return(snapshotStore.GetSnapshot(aggregateRootId) ?? new Snapshot()); }
public Bundle GetPage(string snapshotkey, int start = 0, int count = DEFAULT_PAGE_SIZE) { Snapshot snapshot = snapshotstore.GetSnapshot(snapshotkey); return(GetPage(snapshot, start, count)); }
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));
public Bundle GetPage(string snapshotkey, int start) { Snapshot snapshot = snapshotstore.GetSnapshot(snapshotkey); return(GetPage(snapshot, start)); }