Beispiel #1
0
        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);
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
        /// <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);
        }
Beispiel #6
0
        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();
        }
Beispiel #8
0
        /// <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);
        }
Beispiel #10
0
        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);
                }
            }
        }