private void TryMakeSnapshot(IAggregateRoot <TAuthenticationToken> aggregate) { if (!SnapshotStrategy.ShouldMakeSnapShot(aggregate)) { return; } dynamic snapshot = aggregate.AsDynamic().GetSnapshot().RealObject; snapshot.Version = aggregate.Version + aggregate.GetUncommittedChanges().Count(); SnapshotStore.Save(snapshot); }
private async Task <int> RestoreAggregateFromSnapshot(Guid aggregateId, IAggregateRoot aggregate) { if (!SnapshotStrategy.IsSnapshotable(aggregate.GetType())) { return(-1); } var snapshot = await this._snapshotRepository.GetAsync(aggregateId); if (snapshot == null) { return(-1); } ((dynamic)aggregate).Restore((dynamic)snapshot); return(aggregate.Version); }
private int TryRestoreAggregateFromSnapshot <TAggregateRoot>(Guid id, TAggregateRoot aggregate) { int version = -1; if (SnapshotStrategy.IsSnapshotable(typeof(TAggregateRoot))) { Snapshot snapshot = SnapshotStore.Get(id); if (snapshot != null) { aggregate.AsDynamic().Restore(snapshot); version = snapshot.Version; } } return(version); }
/// <summary> /// Calls <see cref="ISnapshotStrategy{TAuthenticationToken}.IsSnapshotable"/> on <see cref="SnapshotStrategy"/> /// If the <typeparamref name="TAggregateRoot"/> is snapshot-able <see cref="ISnapshotStore.Get{TAggregateRoot}"/> is called on <see cref="SnapshotStore"/>. /// The Restore method is then called on /// </summary> /// <typeparam name="TAggregateRoot">The <see cref="Type"/> of the <see cref="IAggregateRoot{TAuthenticationToken}"/>.</typeparam> /// <param name="id">The identifier of the <see cref="IAggregateRoot{TAuthenticationToken}"/> to restore, since the <paramref name="aggregate"/> may be completely uninitialised.</param> /// <param name="aggregate">The <typeparamref name="TAggregateRoot"/></param> /// <returns>-1 if no restoration was made, otherwise version number the <typeparamref name="TAggregateRoot"/> was rehydrated to.</returns> /// <remarks>There may be more events after the snapshot that still need to rehydrated into the <typeparamref name="TAggregateRoot"/> after restoration.</remarks> protected virtual int TryRestoreAggregateFromSnapshot <TAggregateRoot>(Guid id, TAggregateRoot aggregate) { int version = -1; if (SnapshotStrategy.IsSnapshotable(aggregate.GetType())) { Snapshot snapshot = SnapshotStore.Get(aggregate.GetType(), id); if (snapshot != null) { aggregate.AsDynamic().Restore(snapshot); version = snapshot.Version; } } return(version); }
protected void ApplyCommittedEvent <TAggregateEvent>(ICommittedEvent <TAggregate, TIdentity, TAggregateEvent> committedEvent) where TAggregateEvent : class, IAggregateEvent <TAggregate, TIdentity> { var applyMethods = GetEventApplyMethods(committedEvent.AggregateEvent); applyMethods(committedEvent.AggregateEvent); Log.Info("Aggregate of Name={0}, and Id={1}; committed and applied an AggregateEvent of Type={2}.", Name, Id, typeof(TAggregateEvent).PrettyPrint()); Version++; var domainEvent = new DomainEvent <TAggregate, TIdentity, TAggregateEvent>(Id, committedEvent.AggregateEvent, committedEvent.Metadata, committedEvent.Timestamp, Version); Publish(domainEvent); ReplyIfAvailable(); if (!SnapshotStrategy.ShouldCreateSnapshot(this)) { return; } var aggregateSnapshot = CreateSnapshot(); if (aggregateSnapshot == null) { return; } _snapshotDefinitionService.Load(aggregateSnapshot.GetType()); var snapshotDefinition = _snapshotDefinitionService.GetDefinition(aggregateSnapshot.GetType()); var snapshotMetadata = new SnapshotMetadata { AggregateId = Id.Value, AggregateName = Name.Value, AggregateSequenceNumber = Version, SnapshotName = snapshotDefinition.Name, SnapshotVersion = snapshotDefinition.Version }; var committedSnapshot = new CommittedSnapshot <TAggregate, TIdentity, IAggregateSnapshot <TAggregate, TIdentity> >( Id, aggregateSnapshot, snapshotMetadata, committedEvent.Timestamp, Version); SaveSnapshot(committedSnapshot); }
protected void ApplyCommittedEvent <TAggregateEvent>(ICommittedEvent <TAggregate, TIdentity, TAggregateEvent> committedEvent) where TAggregateEvent : IAggregateEvent <TAggregate, TIdentity> { var applyMethods = GetEventApplyMethods(committedEvent.AggregateEvent); applyMethods(committedEvent.AggregateEvent); Logger.Info($"[{Name}] With Id={Id} Commited and Applied [{typeof(TAggregateEvent).PrettyPrint()}]"); Version++; var domainEvent = new DomainEvent <TAggregate, TIdentity, TAggregateEvent>(Id, committedEvent.AggregateEvent, committedEvent.Metadata, committedEvent.Timestamp, Version); Publish(domainEvent); ReplyIfAvailable(); if (SnapshotStrategy.ShouldCreateSnapshot(this)) { var aggregateSnapshot = CreateSnapshot(); if (aggregateSnapshot != null) { _snapshotDefinitionService.Load(aggregateSnapshot.GetType()); var snapshotDefinition = _snapshotDefinitionService.GetDefinition(aggregateSnapshot.GetType()); var snapshotMetadata = new SnapshotMetadata { AggregateId = Id.Value, AggregateName = Name.Value, AggregateSequenceNumber = Version, SnapshotName = snapshotDefinition.Name, SnapshotVersion = snapshotDefinition.Version }; var commitedSnapshot = new ComittedSnapshot <TAggregate, TIdentity, IAggregateSnapshot <TAggregate, TIdentity> >( Id, aggregateSnapshot, snapshotMetadata, committedEvent.Timestamp, Version); SaveSnapshot(commitedSnapshot); } } }
public async Task SaveAsync <T>(T aggregate) where T : IAggregateRoot { if (aggregate.DomainEvents == null) { return; } await this._eventRepository.SaveAsync(aggregate); if (SnapshotStrategy.ShouldMakeSnapshot(aggregate)) { var snapshot = ((dynamic)aggregate).GetSnapshot(); await this._snapshotRepository.SaveAsync(snapshot); } await PublishEvents(aggregate.DomainEvents); aggregate.ClearDomainEvents(); }
/// <summary> /// Calls <see cref="ISnapshotStrategy{TAuthenticationToken}.ShouldMakeSnapShot"/> on <see cref="SnapshotStrategy"/> /// If the <see cref="IAggregateRoot{TAuthenticationToken}"/> is snapshot-able <see cref="SnapshotAggregateRoot{TAuthenticationToken,TSnapshot}.GetSnapshot"/> is called /// The <see cref="Snapshot.Version"/> is calculated, finally <see cref="ISnapshotStore.Save"/> is called on <see cref="SnapshotStore"/>. /// </summary> /// <param name="aggregate">The <see cref="IAggregateRoot{TAuthenticationToken}"/> to try and snapshot.</param> /// <param name="uncommittedChanges">A collection of uncommited changes to assess. If null the aggregate will be asked to provide them.</param> protected virtual void TryMakeSnapshot(IAggregateRoot <TAuthenticationToken> aggregate, IEnumerable <IEvent <TAuthenticationToken> > uncommittedChanges) { if (!SnapshotStrategy.ShouldMakeSnapShot(aggregate, uncommittedChanges)) { return; } dynamic snapshot = aggregate.AsDynamic().GetSnapshot().RealObject; var rsnapshot = snapshot as Snapshot; if (rsnapshot != null) { rsnapshot.Version = aggregate.Version; SnapshotStore.Save(rsnapshot); } else { snapshot.Version = aggregate.Version; SnapshotStore.Save(snapshot); } }
/// <summary> /// Commits the asynchronous. /// </summary> /// <param name="eventStore">The event store.</param> /// <param name="snapshotStore">The snapshot store.</param> /// <param name="sourceId">The source identifier.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns></returns> public override async Task <IReadOnlyCollection <IDomainEvent> > CommitAsync(IEventStore eventStore, ISnapshotStore snapshotStore, ISourceId sourceId, CancellationToken cancellationToken) { var domainEvents = await CommitDomainEventAsync(eventStore, sourceId, cancellationToken); if (!await SnapshotStrategy.ShouldCreateSnapshotAsync(this, cancellationToken)) { return(domainEvents); } var snapshotContainer = await CreateSnapshotContainerAsync(cancellationToken); await snapshotStore.StoreSnapshotAsync <TAggregate, TIdentity, TSnapshot>( Id, snapshotContainer, cancellationToken) ; return(domainEvents); }
public virtual void Emit <TAggregateEvent>(TAggregateEvent aggregateEvent, IMetadata metadata = null) where TAggregateEvent : IAggregateEvent <TAggregate, TIdentity> { if (aggregateEvent == null) { throw new ArgumentNullException(nameof(aggregateEvent)); } _eventDefinitionService.Load(typeof(TAggregateEvent)); var eventDefinition = _eventDefinitionService.GetDefinition(typeof(TAggregateEvent)); var aggregateSequenceNumber = Version + 1; var eventId = EventId.NewDeterministic( GuidFactories.Deterministic.Namespaces.Events, $"{Id.Value}-v{aggregateSequenceNumber}"); var now = DateTimeOffset.UtcNow; var eventMetadata = new Metadata { Timestamp = now, AggregateSequenceNumber = aggregateSequenceNumber, AggregateName = Name.Value, AggregateId = Id.Value, EventId = eventId, EventName = eventDefinition.Name, EventVersion = eventDefinition.Version }; eventMetadata.Add(MetadataKeys.TimestampEpoch, now.ToUnixTime().ToString()); if (metadata != null) { eventMetadata.AddRange(metadata); } var committedEvent = new CommittedEvent <TAggregate, TIdentity, TAggregateEvent>(Id, aggregateEvent, eventMetadata, now, Version); Persist(committedEvent, ApplyCommittedEvents); Logger.Info($"[{Name}] With Id={Id} Commited [{typeof(TAggregateEvent).PrettyPrint()}]"); Version++; var domainEvent = new DomainEvent <TAggregate, TIdentity, TAggregateEvent>(Id, aggregateEvent, eventMetadata, now, Version); Publish(domainEvent); if (SnapshotStrategy.ShouldCreateSnapshot(this)) { var aggregateSnapshot = CreateSnapshot(); if (aggregateSnapshot != null) { var t = aggregateSnapshot.GetType(); _snapshotDefinitionService.Load(aggregateSnapshot.GetType()); var snapshotDefinition = _snapshotDefinitionService.GetDefinition(aggregateSnapshot.GetType()); var snapshotMetadata = new SnapshotMetadata { AggregateId = Id.Value, AggregateName = Name.Value, AggregateSequenceNumber = Version, SnapshotName = snapshotDefinition.Name, SnapshotVersion = snapshotDefinition.Version }; var commitedSnapshot = new ComittedSnapshot <TAggregate, TIdentity, IAggregateSnapshot <TAggregate, TIdentity> >( Id, aggregateSnapshot, snapshotMetadata, now, Version); SaveSnapshot(commitedSnapshot); } } }