public static IObservable <TSource> Shift <TSource>( this IObservable <TSource> source, long count, IScheduler scheduler) { return(Observable.Create <TSource>(observer => { var limited_queue = new FixedSizedQueue <TSource>(count); return source.Subscribe(value => { if (limited_queue.Shift(value, out var outObj)) { observer.OnNext(outObj); } }, observer.OnError, /* Immediate abort semantics of Rx requires us to propagate * errors immediately (i.e., without draining the queue). * (Exception ex) => * { * limited_queue * .Subscribe(Observer * .Create<TSource>(data => observer.OnNext(data), * () => observer.OnError(ex)), * scheduler); * }*/ () => { limited_queue.ToObservable(scheduler).Subscribe(observer); }); })); }
public static IObservable <TAccumulate> WindowAggregate <TSource, TAccumulate>( this IObservable <TSource> source, long windowSize, TAccumulate seed, Func <TAccumulate, TSource, TSource, long, TAccumulate> accumulator, Func <TAccumulate, TSource, long, long, TAccumulate> windowDrainer) { if (accumulator == null) { throw new ArgumentNullException("WindowAggregate: accumulator can't be null"); } if (windowDrainer == null) { throw new ArgumentNullException("WindowAggregate: windowDrainer can't be null"); } return(Observable.Create <TAccumulate>(observer => { var limitedQueue = new FixedSizedQueue <TSource>(windowSize); return source.Subscribe( value => { try { seed = limitedQueue.Shift(value, out var outObj) ? accumulator(seed, value, outObj, limitedQueue.Count) : windowDrainer(seed, value, limitedQueue.Count, limitedQueue.Count - 1); observer.OnNext(seed); } catch (Exception ex) { observer.OnError(ex); } }, observer.OnError, () => { try { long count = limitedQueue.Count; while (limitedQueue.TryDequeue(out var outObj)) { count--; seed = windowDrainer(seed, outObj, count, count + 1); observer.OnNext(seed); } if (count != 0) { observer.OnError( new ApplicationException( "WindowAggregte: OnCompleted: Unable to deque all elements")); } else { observer.OnCompleted(); } } catch (Exception ex) { observer.OnError(ex); } }); })); }