/// <summary>
        ///  When overriden, defines the custom behavior to be invoked after attempting to save the specified <paramref name="aggregate"/>.
        /// </summary>
        /// <param name="aggregate">The modified <see cref="Aggregate"/> instance if <paramref name="commit"/> is not <value>null</value>; otherwise the original <see cref="Aggregate"/> instance if <paramref name="error"/> is not <value>null</value>.</param>
        /// <param name="commit">The <see cref="Commit"/> generated if the save was successful; otherwise <value>null</value>.</param>
        /// <param name="error">The <see cref="Exception"/> thrown if the save was unsuccessful; otherwise <value>null</value>.</param>
        public override void PostSave(Aggregate aggregate, Commit commit, Exception error)
        {
            base.PostSave(aggregate, commit, error);

            if (error is ConcurrencyException)
                statistics.IncrementConflictCount();
        }
        /// <summary>
        /// Verify that the specified <paramref name="aggregate"/> state has not been corrupted after a failed save attempt and update the check sum if the save was successful.
        /// </summary>
        /// <param name="aggregate">The modified <see cref="Aggregate"/> instance if <paramref name="commit"/> is not <value>null</value>; otherwise the original <see cref="Aggregate"/> instance if <paramref name="error"/> is not <value>null</value>.</param>
        /// <param name="commit">The <see cref="Commit"/> generated if the save was successful; otherwise <value>null</value>.</param>
        /// <param name="error">The <see cref="Exception"/> thrown if the save was unsuccessful; otherwise <value>null</value>.</param>
        public override void PostSave(Aggregate aggregate, Commit commit, Exception error)
        {
            if (error != null)
                aggregate.VerifyHash();

            if (commit != null)
                aggregate.UpdateHash();
        }
        /// <summary>
        /// Initializes a new instance of <see cref="SaveResult"/>.
        /// </summary>
        /// <param name="aggregate">The saved <see cref="Aggregate"/>.</param>
        /// <param name="commit">The generated <see cref="Commit"/></param>
        public SaveResult(Aggregate aggregate, Commit commit)
        {
            Verify.NotNull(aggregate, nameof(aggregate));
            Verify.NotNull(commit, nameof(commit));

            Aggregate = aggregate;
            Commit = commit;
        }
 /// <summary>
 ///  When overriden, defines the custom behavior to be invoked after attempting to save the specified <paramref name="aggregate"/>.
 /// </summary>
 /// <param name="aggregate">The modified <see cref="Aggregate"/> instance if <paramref name="commit"/> is not <value>null</value>; otherwise the original <see cref="Aggregate"/> instance if <paramref name="error"/> is not <value>null</value>.</param>
 /// <param name="commit">The <see cref="Commit"/> generated if the save was successful; otherwise <value>null</value>.</param>
 /// <param name="error">The <see cref="Exception"/> thrown if the save was unsuccessful; otherwise <value>null</value>.</param>
 public override void PostSave(Aggregate aggregate, Commit commit, Exception error)
 {
     if (commit?.Id != null)
         DispatchCommit(commit);
     else
         Log.Warn("Commit not dispatched");
 }
        /// <summary>
        /// Dispatch all events within the specified <paramref name="commit"/>.
        /// </summary>
        /// <param name="commit">The commit instance to be dispatched.</param>
        private void DispatchCommit(Commit commit)
        {
            var commitId = commit.Id.GetValueOrDefault();
            var events = commit.Events;

            for (var i = 0; i < events.Count; i++)
            {
                var e = events[i];
                var version = new EventVersion(commit.Version, events.Count, i + 1);

                eventPublisher.Publish(commit.Headers, new EventEnvelope(commit.CorrelationId, commit.StreamId, version, e));
            }

            if (markDispatched)
                eventStore.MarkDispatched(commitId);
        }
 /// <summary>
 ///  When overriden, defines the custom behavior to be invoked after attempting to save the specified <paramref name="aggregate"/>.
 /// </summary>
 /// <param name="aggregate">The modified <see cref="Aggregate"/> instance if <paramref name="commit"/> is not <value>null</value>; otherwise the original <see cref="Aggregate"/> instance if <paramref name="error"/> is not <value>null</value>.</param>
 /// <param name="commit">The <see cref="Commit"/> generated if the save was successful; otherwise <value>null</value>.</param>
 /// <param name="error">The <see cref="Exception"/> thrown if the save was unsuccessful; otherwise <value>null</value>.</param>
 public virtual void PostSave(Aggregate aggregate, Commit commit, Exception error)
 {
 }
        /// <summary>
        /// Appends a new commit to the event store.
        /// </summary>
        /// <param name="commit">The commit to append to the event store.</param>
        public void Save(Commit commit)
        {
            eventStore.Save(commit);

            if (commit.Version == 1)
                statistics.IncrementInsertCount();
            else
                statistics.IncrementUpdateCount();
        }
        /// <summary>
        /// Applies all <see cref="Commit.Events"/> to the specified <paramref name="aggregate"/> instance.
        /// </summary>
        /// <param name="commit">The <see cref="Commit"/> to be applied to the specified <paramref name="aggregate"/>.</param>
        /// <param name="aggregate">The <see cref="Aggregate"/> instance for which the commit is to be applied.</param>
        private void ApplyCommitToAggregate(Commit commit, Aggregate aggregate)
        {
            var expectedVersion = aggregate.Version + 1;
            if (commit.Version != expectedVersion)
                throw new InvalidOperationException(Exceptions.MissingAggregateCommits.FormatWith(expectedVersion, commit.Version));

            aggregate.Version = commit.Version;
            foreach (var e in commit.Events)
            {
                using (new EventContext(aggregate.Id, commit.Headers, e))
                    aggregateUpdater.Apply(e, aggregate);
            }
        }
 /// <summary>
 /// Invokes zero or more customized <see cref="PipelineHook.PostSave"/> implementations.
 /// </summary>
 /// <param name="aggregate">The modified <see cref="Aggregate"/> instance if <paramref name="commit"/> is not <value>null</value>; otherwise the original <see cref="Aggregate"/> instance if <paramref name="error"/> is not <value>null</value>.</param>
 /// <param name="commit">The <see cref="Commit"/> generated if the save was successful; otherwise <value>null</value>.</param>
 /// <param name="error">The <see cref="Exception"/> thrown if the save was unsuccessful; otherwise <value>null</value>.</param>
 private void InvokePostSaveHooks(Aggregate aggregate, Commit commit, Exception error)
 {
     foreach (var pipelineHook in postSaveHooks)
     {
         Log.Trace("Invoking post-save pipeline hook: {0}", pipelineHook);
         pipelineHook.PostSave(aggregate, commit, error);
     }
 }