Beispiel #1
0
        /// <summary>
        /// Gets all aggregate events bundles.
        /// </summary>
        /// <param name="aggregateUid">The aggregate uid.</param>
        /// <returns></returns>
        public IEnumerable <AggregateEventsBundle> GetAllAggregateEventsBundles(Guid aggregateUid)
        {
            AggregateEventsBundle bundle = new AggregateEventsBundle();

            bundle.AggregateUid = aggregateUid;
            var allBundlers = this.provider.GetValuesByKeyPattern <AggregateEventsBundle>(bundle.DocumentKey, string.Empty, true);

            return(allBundlers);
        }
Beispiel #2
0
        /// <summary>
        /// Gets the aggregate events bundle.
        /// </summary>
        /// <param name="aggregateUid">The aggregate uid.</param>
        /// <param name="bundleNumber">The bundle number.</param>
        /// <returns></returns>
        public AggregateEventsBundle GetAggregateEventsBundle(Guid aggregateUid, int?bundleNumber = null)
        {
            AggregateEventsBundle bundle = new AggregateEventsBundle()
            {
                AggregateUid = aggregateUid, BundleNumber = bundleNumber
            };

            bundle = this.provider.GetValue <AggregateEventsBundle>(bundle.DocumentKey);
            return(bundle);
        }
Beispiel #3
0
        private IEnumerable <AggregateEventsBundle> GetAndUpdateAggregateBundles(Guid aggregateUid)
        {
            var newEvents  = this.workContext.Events.Where(x => x.AggregateUid == aggregateUid);
            var markedAsyn = this.workContext.MarkedAsyncProcessed.Where(x => x.AggregateUid == aggregateUid);

            int minVersion = 0;
            var allEvents  = newEvents.Union(markedAsyn);

            if (allEvents.Count() > 0)
            {
                minVersion = allEvents.Min(x => x.AggregateVersion);
            }

            var currentBundle = this.loader.GetAggregateEventsBundle(aggregateUid);

            if (currentBundle == null)
            {
                currentBundle = new AggregateEventsBundle()
                {
                    AggregateUid = aggregateUid
                }
            }
            ;

            List <AggregateEventsBundle> allBundles = GetAllNecessaryBundles(aggregateUid, minVersion, currentBundle);

            // save new events
            foreach (var @event in newEvents)
            {
                if (allBundles.Any(bundle => bundle.Events.Any(x => x.AggregateVersion == @event.AggregateVersion)))
                {
                    throw new ConcurrencyException("The item with id {0} is already inserted".InvariantFormat(@event.DocumentKey));
                }
                else
                {
                    @event.SystemVersion = this.provider.ReserveCounter();
                    this.aggregateEventContext.AttachToEvent(@event);
                    currentBundle.Events = currentBundle.Events.FluentAdd(@event);
                }
            }

            // save events marked async.
            foreach (var @event in markedAsyn)
            {
                var bundle = allBundles.Where(x => x.Events.Any(y => y.AggregateVersion == @event.AggregateVersion)).FirstOrDefault();
                if (bundle == null)
                {
                    throw new LendsumException(S.Invariant($"The event version {@event.AggregateVersion} of aggregate {aggregateUid} cannot be marked as async processed because cannot be found"));
                }

                bundle.Events.Where(x => x.AggregateVersion == @event.AggregateVersion).First().AsyncProcessed = true;
            }

            return(allBundles);
        }
Beispiel #4
0
        /// <summary>
        /// Consumes the specified incoming event.
        /// </summary>
        /// <param name="aggregateUid">The aggregate uid.</param>
        public void SnapShotIfNeeded(Guid aggregateUid)
        {
            var aggregate = this.loader.Load(aggregateUid);

            if (aggregate != null &&
                aggregate.ReadyForSnapShot &&
                aggregate.Events.Count() > 0 &&
                aggregate.Events.All(x => x.AsyncProcessed == true))
            {
                var raw = this.serializer.Serialize(aggregate);
                AggregateSnapshot snapshot = new AggregateSnapshot();
                snapshot.AggregateSerialized = raw;
                snapshot.AggregateVersion    = aggregate.Version;
                snapshot.SnapShotTypeVersion = aggregate.SnapShotTypeVersion;

                var currentBundler = this.loader.GetAggregateEventsBundle(aggregateUid);
                AggregateEventsBundle oldBundler = null;

                if (currentBundler.Events.Where(x => x.AggregateVersion <= aggregate.Version).Any())
                {
                    oldBundler = new AggregateEventsBundle();
                    oldBundler.AggregateUid         = aggregateUid;
                    oldBundler.PreviousBundleNumber = currentBundler.PreviousBundleNumber;
                    oldBundler.BundleNumber         = (currentBundler.PreviousBundleNumber ?? 0) + 1;
                    oldBundler.Events = currentBundler.Events.Where(x => x.AggregateVersion <= aggregate.Version).ToArray();
                }

                var newBundler = new AggregateEventsBundle();
                newBundler.AggregateUid = aggregateUid;
                newBundler.Snapshot     = snapshot;

                newBundler.PreviousBundleNumber = oldBundler == null ? currentBundler.PreviousBundleNumber : oldBundler.BundleNumber;
                newBundler.Events = currentBundler.Events.Where(x => x.AggregateVersion > aggregate.Version).ToArray();
                newBundler.Cas    = currentBundler.Cas;

                using (var transaction = this.provider.BeginScope())
                {
                    var result = this.provider.UpdateOrInsert(newBundler);
                    if (result == PersistenceResultEnum.Success)
                    {
                        if (oldBundler != null)
                        {
                            this.provider.Insert(oldBundler);
                        }
                    }

                    transaction.Commit();
                }
            }
        }
Beispiel #5
0
        private List <AggregateEventsBundle> GetAllNecessaryBundles(Guid aggregateUid, int minVersion, AggregateEventsBundle currentBundle)
        {
            List <AggregateEventsBundle> allBundles = new List <AggregateEventsBundle>();

            allBundles.Add(currentBundle);
            var previousBundleNumber = currentBundle.PreviousBundleNumber;

            // find all necessary bundles
            bool found = false;

            while (found == false)
            {
                if (allBundles.Any(b => b.Events.Any(e => e.AggregateVersion >= minVersion)))
                {
                    found = true;
                }
                else
                {
                    // take next bundle
                    if (previousBundleNumber.HasValue)
                    {
                        var previousBundle = this.loader.GetAggregateEventsBundle(aggregateUid, previousBundleNumber.Value);
                        if (previousBundle == null)
                        {
                            throw new LendsumException(S.Invariant($"The bundle {previousBundleNumber.Value} of aggregate {aggregateUid} cannot be found"));
                        }

                        allBundles.Add(previousBundle);
                        previousBundleNumber = previousBundle.PreviousBundleNumber;
                    }
                    else
                    {
                        found = true;
                    }
                }
            }

            return(allBundles);
        }