Ejemplo n.º 1
0
        /// <summary>
        /// Catch up with the stream (updating the state) until there are no new
        /// events available.
        /// </summary>
        public async Task CatchUpAsync(CancellationToken cancel = default)
        {
            Func <bool> finishFetch;

            // Local variable, to avoid reaching the limit when not doing the
            // initial catch-up.
            var eventsSinceLastCacheLoad = 0u;

            do
            {
                var fetchTask = Stream.BackgroundFetchAsync(cancel);

                // We have started fetching the next batch of events in
                // the background, so we might as well start processing
                // those we already have. This pattern is optimized for
                // when fetching events takes longer than processing them,
                // and remains safe (i.e. no runaway memory usage) when
                // the reverse is true.
                eventsSinceLastCacheLoad += CatchUpLocal();

                // Maybe we have reached the event count limit before our
                // save/load cycle ?
                if (eventsSinceLastCacheLoad >= EventsBetweenCacheSaves)
                {
                    eventsSinceLastCacheLoad = 0;
                    var sw = Stopwatch.StartNew();
                    if (await _projection.TrySaveAsync(cancel))
                    {
                        // Reset first, to release any used memory.
                        _projection.Reset();

                        await _projection.TryLoadAsync(cancel);

                        if (_projection.Sequence != Stream.Sequence)
                        {
                            throw new InvalidOperationException(
                                      "Projection Save/Load cycle failed to restore sequence.");
                        }

                        _log.Info($"[ES read] cache save/load cycle in {sw.Elapsed} at seq {_projection.Sequence}.");
                    }
                }

                finishFetch = await fetchTask;
            } while (finishFetch());

            // We reach this point if 1° all events cached in the stream have
            // been processed and 2° the fetch operation returned no new events

            NotifyRefresh();
        }
Ejemplo n.º 2
0
 /// <summary> Attempt to save the projection to the cache. </summary>
 /// <remarks>
 /// While this returns a task, the save operation itself does not touch the
 /// object (only an immutable copy of the state), so you do not need to
 /// wait for this task to finish before starting another operation.
 /// </remarks>
 public Task TrySaveAsync(CancellationToken cancel = default(CancellationToken))
 {
     return(_projection.TrySaveAsync(cancel));
 }
Ejemplo n.º 3
0
 /// <summary> Attempt to save the projection to the cache. </summary>
 /// <remarks>
 /// While this returns a task, the save operation itself does not touch the
 /// object (only an immutable copy of the state), so you do not need to
 /// wait for this task to finish before starting another operation.
 /// </remarks>
 public Task TrySaveAsync(CancellationToken cancel = default) =>
 _projection.TrySaveAsync(cancel);