/// <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> /// 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> /// Consumes a single batch from the source stream and updates the subscribed aggregators. /// </summary> /// <returns> /// The updated cursor position after the batch is consumed. /// </returns> public override async Task <ICursor <TUpstreamCursor> > RunSingleBatch() { return(await upstreamCatchup.RunSingleBatch()); }