/// <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)); }
/// <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())); }
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> >())); }
/// <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; })); }
/// <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); }
/// <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); }
/// <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))) { }