Ejemplo n.º 1
0
        public void Save(IAggregateRoot aggregate)
        {
            var uncommittedChanges = aggregate.GetUncommittedChanges();
            var version            = aggregate.Version;

            foreach (var uncommittedChange in uncommittedChanges)
            {
                version++;
                if (version > 2)
                {
                    if (version % 3 == 0)
                    {
                        var originator = (IOriginator)aggregate;
                        var memento    = originator.GetMemento();
                        memento.Version = version;
                        SaveMemento(memento);
                    }
                }

                uncommittedChange.Version = version;
                _events.Add(uncommittedChange);
            }

            foreach (var uncommittedChange in uncommittedChanges)
            {
                dynamic targetEvent = Convert.ChangeType(uncommittedChange, uncommittedChange.GetType());
                _eventBus.Publish(targetEvent);
            }
        }
Ejemplo n.º 2
0
        public void SaveAggregate(IAggregateRoot aggregate)
        {
            var expectedVersion = aggregate.Version;

            //get aggregate version by id
            var version = eventStore.GetVersionByAggregate(aggregate.Id);

            //check consistency...
            if (version.HasValue && version != expectedVersion)
            {
                throw new ConsistencyException(aggregate.Id);
            }

            var newVersion = expectedVersion.HasValue ? expectedVersion : 0;

            foreach (var @event in aggregate.GetUncommittedChanges())
            {
                newVersion++;
                @event.Version = newVersion.Value;
                eventStore.Save(@event);
                eventBus.PublishEvent(@event);
            }

            aggregate.MarkChangesAsCommitted();
        }
Ejemplo n.º 3
0
        public virtual void Save(IAggregateRoot aggregateRoot, int expectedVersion)
        {
            var eventStorage = Ioc.Instance.Resolve <IEventStorage>();

            if (!aggregateRoot.GetUncommittedChanges().Any())
            {
                //TODO: In order to debug, save single aggregate instance.
                //return;
            }

            lock (Locker)
            {
                var entity = new TAggregateRoot();
                if (expectedVersion != -1)
                {
                    entity = GetById(aggregateRoot.Id);
                }

                if (entity.Version != expectedVersion)
                {
                    throw new Exception($"Entity {aggregateRoot} has been modified previously");
                }

                eventStorage.Save(aggregateRoot);
            }
        }
Ejemplo n.º 4
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);
        }
Ejemplo n.º 5
0
        public void Save(IAggregateRoot aggregate)
        {
            if (aggregate is null)
            {
                throw new ArgumentNullException(nameof(aggregate));
            }

            _storage.SaveEvents(
                aggregate.Id,
                aggregate.GetUncommittedChanges().ToArray());
        }
Ejemplo n.º 6
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>
        protected virtual void TryMakeSnapshot(IAggregateRoot <TAuthenticationToken> aggregate)
        {
            if (!SnapshotStrategy.ShouldMakeSnapShot(aggregate))
            {
                return;
            }
            dynamic snapshot  = aggregate.AsDynamic().GetSnapshot().RealObject;
            var     rsnapshot = snapshot as Snapshot;

            if (rsnapshot != null)
            {
                rsnapshot.Version = aggregate.Version + aggregate.GetUncommittedChanges().Count();
                SnapshotStore.Save(rsnapshot);
            }
            else
            {
                snapshot.Version = aggregate.Version + aggregate.GetUncommittedChanges().Count();
                SnapshotStore.Save(snapshot);
            }
        }
Ejemplo n.º 7
0
        public bool ShouldMakeSnapShot(IAggregateRoot <TAuthenticationToken> aggregate)
        {
            if (!IsSnapshotable(aggregate.GetType()))
            {
                return(false);
            }
            int i = aggregate.Version;

            int limit = aggregate.GetUncommittedChanges().Count();

            for (int j = 0; j < limit; j++)
            {
                if (++i % SnapshotInterval == 0 && i != 0)
                {
                    return(true);
                }
            }
            return(false);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Checks <see cref="IsSnapshotable"/> and if it is, also checks if the calculated version number would be exactly dividable by <see cref="GetSnapshotInterval"/>.
        /// </summary>
        /// <param name="aggregate">The <see cref="IAggregateRoot{TAuthenticationToken}"/> to check.</param>
        public virtual bool ShouldMakeSnapShot(IAggregateRoot <TAuthenticationToken> aggregate)
        {
            if (!IsSnapshotable(aggregate.GetType()))
            {
                return(false);
            }

            // Why isn't this something as simple as `(aggregate.Version + aggregate.GetUncommittedChanges().Count()) % SnapshotInterval`???
            int i = aggregate.Version;

            int limit = aggregate.GetUncommittedChanges().Count();

            for (int j = 0; j < limit; j++)
            {
                if (++i % GetSnapshotInterval() == 0 && i != 0)
                {
                    return(true);
                }
            }
            return(false);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Checks <see cref="IsSnapshotable"/> and if it is, also checks if the calculated version number would be exactly dividable by <see cref="GetSnapshotInterval"/>.
        /// </summary>
        /// <param name="aggregate">The <see cref="IAggregateRoot{TAuthenticationToken}"/> to check.</param>
        /// <param name="uncommittedChanges">A collection of uncommited changes to assess. If null the aggregate will be asked to provide them.</param>
        public virtual bool ShouldMakeSnapShot(IAggregateRoot <TAuthenticationToken> aggregate, IEnumerable <IEvent <TAuthenticationToken> > uncommittedChanges = null)
        {
            if (!IsSnapshotable(aggregate.GetType()))
            {
                return(false);
            }

            // The reason this isn't as simple as `(aggregate.Version + aggregate.GetUncommittedChanges().Count()) % SnapshotInterval` is
            // because if there are enough uncommited events that this would result in a snapshot, plus some left over, the final state is what will be generated
            // when the snapshot is taken, thus this is a faster and more accurate assessment.
            int limit            = (uncommittedChanges ?? aggregate.GetUncommittedChanges()).Count();
            int i                = aggregate.Version - limit;
            int snapshotInterval = GetSnapshotInterval();

            for (int j = 0; j < limit; j++)
            {
                if (++i % snapshotInterval == 0 && i != 0)
                {
                    return(true);
                }
            }
            return(false);
        }
Ejemplo n.º 10
0
        public void Save(IAggregateRoot aggregateRoot, int expectedVersion)
        {
            if (!aggregateRoot.GetUncommittedChanges().Any())
            {
                return;
            }

            lock (Locker)
            {
                var entity = new TAggregateRoot();
                if (expectedVersion != -1)
                {
                    entity = GetById(aggregateRoot.Id);
                }

                if (entity.Version != expectedVersion)
                {
                    throw new Exception($"Entity {aggregateRoot} has been modified previously");
                }

                _eventStorage.Save(entity);
            }
        }
Ejemplo n.º 11
0
 public void Save(IAggregateRoot aggregate, int expectedRevision)
 {
     _storage.SaveEvents(aggregate.Id, aggregate.GetUncommittedChanges(), expectedRevision);
 }
Ejemplo n.º 12
0
        /// <summary>
        /// Save all changes
        /// </summary>
        /// <param name="aggregate"></param>
        /// <param name="handleEventsSynchronously"></param>
        public async Task SaveAsync(IAggregateRoot aggregate)
        {
            await _eventStore.SaveEventsAsync(aggregate.Id, aggregate.CurrentVersion, aggregate.GetUncommittedChanges());

            aggregate.MarkChangesAsCommitted();
        }