Beispiel #1
0
 /// <summary>
 /// Subscribes the specified aggregator to a catchup.
 /// </summary>
 /// <typeparam name="TProjection">The type of the projection.</typeparam>
 /// <typeparam name="TData">The type of the stream's data.</typeparam>
 /// <typeparam name="TCursor">The type of the cursor.</typeparam>
 /// <param name="catchup">The catchup.</param>
 /// <param name="aggregator">The aggregator.</param>
 /// <returns>A disposable that, when disposed, unsubscribes the aggregator.</returns>
 public static IDisposable Subscribe <TProjection, TData, TCursor>(
     this IStreamCatchup <TData, TCursor> catchup,
     IStreamAggregator <TProjection, TData> aggregator,
     FetchAndSaveProjection <TProjection> manageProjection,
     HandleAggregatorError <TProjection> onError = null)
 {
     return(catchup.SubscribeAggregator(aggregator, manageProjection, onError));
 }
Beispiel #2
0
 /// <summary>
 /// Subscribes the specified aggregator to a catchup.
 /// </summary>
 /// <typeparam name="TProjection">The type of the projection.</typeparam>
 /// <typeparam name="TData">The type of the stream's data.</typeparam>
 /// <typeparam name="TCursor">The type of the cursor.</typeparam>
 /// <param name="catchup">The catchup.</param>
 /// <param name="aggregate">A delegate that performs an aggregate operation on projections receiving new data.</param>
 /// <param name="projectionStore">The projection store.</param>
 /// <returns>
 /// A disposable that, when disposed, unsubscribes the aggregator.
 /// </returns>
 public static IDisposable Subscribe <TProjection, TData, TCursor>(
     this IStreamCatchup <TData, TCursor> catchup,
     AggregateAsync <TProjection, TData> aggregate,
     IProjectionStore <string, TProjection> projectionStore = null)
 {
     return(catchup.Subscribe(Aggregator.Create(aggregate),
                              projectionStore.AsHandler()));
 }
Beispiel #3
0
 public static IDisposable Subscribe <TData, TCursor>(
     this IStreamCatchup <TData, TCursor> catchup,
     Func <IStreamBatch <TData>, Task> aggregate)
 {
     return(catchup.Subscribe(
                Aggregator.Create <Projection <Unit, TCursor>, TData>(async(p, b) =>
     {
         await aggregate(b);
         return p;
     }),
                new InMemoryProjectionStore <Projection <Unit, TCursor> >()));
 }
Beispiel #4
0
        /// <summary>
        /// Runs catchup batches repeatedly with a specified interval after each batch.
        /// </summary>
        /// <typeparam name="TData">The type of the stream's data.</typeparam>
        /// <typeparam name="TCursor">The type of the cursor.</typeparam>
        /// <param name="catchup">The catchup.</param>
        /// <param name="pollInterval">The amount of time to wait after each batch is processed.</param>
        /// <returns>A disposable that, when disposed, stops the polling.</returns>
        public static IDisposable Poll <TData, TCursor>(
            this IStreamCatchup <TData, TCursor> catchup,
            TimeSpan pollInterval)
        {
            var canceled = false;

            Task.Run(async() =>
            {
                while (!canceled)
                {
                    await catchup.RunSingleBatch();
                    await Task.Delay(pollInterval);
                }
            });

            return(Disposable.Create(() => { canceled = true; }));
        }
Beispiel #5
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MultiStreamCatchup{TData, TUpstreamCursor, TDownstreamCursor}"/> class.
        /// </summary>
        /// <param name="upstreamCatchup">The upstream catchup.</param>
        /// <exception cref="ArgumentNullException">
        /// upstreamCatchup
        /// or
        /// manageCursor
        /// </exception>
        public MultiStreamCatchup(
            IStreamCatchup <IStream <TData, TDownstreamCursor>, TUpstreamCursor> upstreamCatchup,
            FetchAndSaveProjection <ICursor <TUpstreamCursor> > manageCursor)
        {
            if (upstreamCatchup == null)
            {
                throw new ArgumentNullException("upstreamCatchup");
            }
            if (manageCursor == null)
            {
                throw new ArgumentNullException("manageCursor");
            }
            this.upstreamCatchup = upstreamCatchup;

            upstreamCatchup.Subscribe(
                async(cursor, streams) =>
            {
                // ths upstream cursor is not passed here because the downstream streams have their own independent cursors
                await Task.WhenAll(streams.Select(stream => RunSingleBatch(stream)));

                return(cursor);
            },
                manageCursor);
        }
Beispiel #6
0
        /// <summary>
        /// Runs the catchup query until it reaches an empty batch, then stops.
        /// </summary>
        public static async Task <ICursor <TCursor> > RunUntilCaughtUp <TData, TCursor>(this IStreamCatchup <TData, TCursor> catchup)
        {
            ICursor <TCursor> cursor;
            var counter = new Counter <TData>();

            using (catchup.Subscribe(async(_, batch) => counter.Count(batch), NoCursor(counter)))
            {
                int countBefore;
                do
                {
                    countBefore = counter.Value;
                    cursor      = await catchup.RunSingleBatch();
                } while (countBefore != counter.Value);
            }

            return(cursor);
        }
Beispiel #7
0
 /// <summary>
 /// Initializes a new instance of the <see cref="MultiStreamCatchup{TData, TUpstreamCursor, TDownstreamCursor}"/> class.
 /// </summary>
 /// <param name="upstreamCatchup">The upstream catchup.</param>
 /// <param name="upstreamCursor">The upstream cursor.</param>
 public MultiStreamCatchup(
     IStreamCatchup <IStream <TData, TDownstreamCursor>, TUpstreamCursor> upstreamCatchup,
     ICursor <TUpstreamCursor> upstreamCursor) : this(upstreamCatchup, (async(streamId, update) => await update(upstreamCursor)))
 {
 }