/// <summary>
        ///     Gets <see cref="ICompletes{TResult}" />, applying <paramref name="state" />,
        ///     dispatching to <code>State(T state)</code> when completed, and supply an
        ///     eventual outcome by means of the given <code>andThen</code> function.
        /// </summary>
        /// <param name="state">The state to preserve.</param>
        /// <param name="andThen">
        ///     The <see cref="CompletionSupplier{TResult}" /> that will provide the fully updated state following this operation,
        ///     and which will used to answer an eventual outcome to the client of this entity
        /// </param>
        /// <typeparam name="TSource">The type of the source.</typeparam>
        /// <typeparam name="TResult">The return type of the Supplier function, which is the type of the completed state.</typeparam>
        /// <returns><see cref="ICompletes{TResult}" />.</returns>
        protected ICompletes <TResult> Apply <TSource, TResult>(T state, Func <TResult>?andThen)
        {
            var completionSupplier = CompletionSupplier <TResult> .SupplierOrNull(andThen, CompletesEventually());

            var completes = andThen == null ? null : Completes();

            StowMessages(typeof(IPersistResultInterest));
            _info.Store.Persist(StateSources <T, Source <TSource> > .Of(state), _persistResultInterest, completionSupplier);
            return((ICompletes <TResult>)completes !);
        }
        public void TestThatMultiPersistQueryResolves()
        {
            _dispatcher.AfterCompleting(3);
            var persistAllAccess = _persistInterest.AfterCompleting(1);

            var person1 = new Person("Tom Jones", 78);
            var person2 = new Person("Dean Martin", 78);
            var person3 = new Person("Sally Struthers", 71);

            _objectStore.PersistAll(new List <StateSources <Person, Test1Source> >
            {
                StateSources <Person, Test1Source> .Of(person1),
                StateSources <Person, Test1Source> .Of(person2),
                StateSources <Person, Test1Source> .Of(person3)
            }, _persistInterest);
            var persistSize = persistAllAccess.ReadFrom <int>("size");

            Assert.Equal(3, persistSize);

            var queryAllAccess = _queryResultInterest.AfterCompleting(1);

            _objectStore.QueryAll(QueryExpression.Using <Person>("findAll"), _queryResultInterest, null);
            var querySize = queryAllAccess.ReadFrom <int>("size");

            Assert.Equal(3, querySize);
            Assert.Equal(person1, queryAllAccess.ReadFrom <int, object>("object", 0));
            Assert.Equal(person2, queryAllAccess.ReadFrom <int, object>("object", 1));
            Assert.Equal(person3, queryAllAccess.ReadFrom <int, object>("object", 2));

            Assert.Equal(3, _dispatcher.DispatchedCount());

            var dispatched = _dispatcher.GetDispatched()[0];

            ValidateDispatchedState(person1, dispatched);
            var dispatchedEntries = dispatched.Entries;

            Assert.Empty(dispatchedEntries);

            dispatched = _dispatcher.GetDispatched()[1];
            ValidateDispatchedState(person2, dispatched);
            dispatchedEntries = dispatched.Entries;
            Assert.Empty(dispatchedEntries);

            dispatched = _dispatcher.GetDispatched()[2];
            ValidateDispatchedState(person3, dispatched);
            dispatchedEntries = dispatched.Entries;
            Assert.Empty(dispatchedEntries);
        }
        public void TestThatObjectPersistsQueries()
        {
            _dispatcher.AfterCompleting(1);
            var persistAccess = _persistInterest.AfterCompleting(1);
            var person        = new Person("Tom Jones", 85);
            var source        = new Test1Source();

            _objectStore.Persist(StateSources <Person, Test1Source> .Of(person, source), _persistInterest);
            var persistSize = persistAccess.ReadFrom <int>("size");

            Assert.Equal(1, persistSize);
            Assert.Equal(person, persistAccess.ReadFrom <int, object>("object", 0));

            var query = MapQueryExpression.Using <Person>("find", MapQueryExpression.Map("id", person.PersistenceId));

            var queryAccess = _queryResultInterest.AfterCompleting(1);

            _objectStore.QueryObject(query, _queryResultInterest, null);
            var querySize = queryAccess.ReadFrom <int>("size");

            Assert.Equal(1, querySize);
            Assert.Equal(person, queryAccess.ReadFrom <int, object>("object", 0));

            Assert.Equal(1, _dispatcher.DispatchedCount());
            var dispatched = _dispatcher.GetDispatched()[0];

            ValidateDispatchedState(person, dispatched);

            var dispatchedEntries = dispatched.Entries;

            Assert.Single(dispatchedEntries);
            var entry = dispatchedEntries[0];

            Assert.NotNull(entry.Id);
            Assert.Equal(source.GetType().AssemblyQualifiedName, entry.TypeName);
            Assert.Equal(Metadata.NullMetadata(), entry.Metadata);
        }
        public void Persist <TNewState, TSource>(StateSources <TNewState, TSource> stateSources, Metadata metadata, long updateId, IPersistResultInterest interest, object? @object) where TNewState : StateObject where TSource : ISource
        {
            try
            {
                var stateObject = stateSources.StateObject;
                var sources     = stateSources.Sources;
                var raw         = _storeDelegate.Persist(stateObject, updateId, metadata);

                var entryVersion = (int)stateSources.StateObject.Version;
                var entries      = _entryAdapterProvider.AsEntries <TSource, IEntry <T> >(sources, entryVersion, metadata).ToList();
                var dispatchable = BuildDispatchable(raw, entries);

                _storeDelegate.PersistEntries(entries);
                _storeDelegate.PersistDispatchable(dispatchable);

                Dispatch(dispatchable);
                interest.PersistResultedIn(Success.Of <StorageException, Result>(Result.Success), stateObject, 1, 1, @object);
            }
            catch (StorageException e)
            {
                Logger.Error("Failed to persist all objects", e);
                interest.PersistResultedIn(Failure.Of <StorageException, Result>(e), null, 0, 0, @object);
            }
        }
 public void Persist <TNewState, TSource>(StateSources <TNewState, TSource> stateSources, IPersistResultInterest interest) where TNewState : StateObject where TSource : ISource
 => Persist(stateSources, Metadata.NullMetadata(), -1, interest, null);
 public void Persist <TNewState, TSource>(StateSources <TNewState, TSource> stateSources, long updateId, IPersistResultInterest interest, object? @object) where TNewState : StateObject where TSource : ISource
 => Persist(stateSources, Metadata.NullMetadata(), updateId, interest, @object);
 public void Persist <TNewState, TSource>(StateSources <TNewState, TSource> stateSources, Metadata metadata, long updateId, IPersistResultInterest interest)
     where TNewState : StateObject where TSource : ISource => Persist(stateSources, metadata, updateId, interest, null);
 public void Persist <TNewState, TSource>(StateSources <TNewState, TSource> stateSources, Metadata metadata, IPersistResultInterest interest, object? @object)
     where TNewState : StateObject where TSource : ISource => Persist(stateSources, metadata, -1, interest, @object);