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); } }
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(); }
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); } }
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); }
public void Save(IAggregateRoot aggregate) { if (aggregate is null) { throw new ArgumentNullException(nameof(aggregate)); } _storage.SaveEvents( aggregate.Id, aggregate.GetUncommittedChanges().ToArray()); }
/// <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); } }
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); }
/// <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); }
/// <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); }
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); } }
public void Save(IAggregateRoot aggregate, int expectedRevision) { _storage.SaveEvents(aggregate.Id, aggregate.GetUncommittedChanges(), expectedRevision); }
/// <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(); }