/// <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); }
/// <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); }
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); }
/// <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(); } } }
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); }