public static IObservableQuery <Continuation <T[]>, TFilter> CreateQueryableStore <T, TFilter, TEvent>(this IObservable <TEvent> stream, Func <T[]> store, ISubject <TFilter> filterStream, Func <TFilter, T, bool> filerFunc, ContinuationToken token, Func <TEvent, bool> updateWhen, IScheduler scheduler = null) { var storeObs = stream.Where(updateWhen).Select(_ => store()); return(new ObservableQuery <Continuation <T[]>, TFilter>( (f, p) => storeObs .StartWith <T[]>(store()) .Select(allRecords => { var currentTokenMeta = PagingToken.FromToken(p.Token, p.Size); var pagedView = allRecords; try { if (f != null) //apply filter if specified { pagedView = allRecords.Where(r => filerFunc(f, r)).ToArray(); } if (p.Size.HasValue) //apply record limiter / pager if specified { var offset = currentTokenMeta.Index.HasValue ? currentTokenMeta.Index.Value - 1 : 0; pagedView = pagedView.Skip(offset * p.Size.Value).Take(p.Size.Value).ToArray(); } } catch (Exception e) { Debug.WriteLine("QueryableStore Size or Filter function failure: {0}", e); } var total = pagedView.Length == 0 ? 0 : allRecords.Length + 1; var nextPageToken = currentTokenMeta.Next(pagedView.Length, total); var nextToken = p.Next(nextPageToken.ToString(), total, nextPageToken.HasMorePages()); return new Continuation <T[]>(pagedView, nextToken); }).Where(w => w.Records.Length > 0), filterStream, token, scheduler )); }
public static IObservable <T[]> CreateQueryableStore1 <T, TFilter, TEvent>(this IObservable <TEvent> stream, Func <TFilter, ContinuationToken, IObservable <Continuation <T[]> > > queryFunc, Func <T[]> store, ISubject <TFilter> filterStream, Func <TFilter, T, bool> filerFunc, ContinuationToken token, Func <TEvent, bool> updateWhen, IScheduler scheduler = null) { Func <TFilter, ContinuationToken, IObservable <T[]> > localQueryFunc = (f, p) => store() .ToObservable() .Select(allRecords => { var currentTokenMeta = PagingToken.FromToken(p.Token, p.Size); var pagedView = allRecords; try { if (f != null) //apply filter if specified { pagedView = allRecords.Where(r => filerFunc(f, r)).ToArray(); } if (p.Size.HasValue) //apply record limiter / pager if specified { var offset = currentTokenMeta.Index.HasValue ? currentTokenMeta.Index.Value - 1 : 0; pagedView = pagedView.Skip(offset * p.Size.Value).Take(p.Size.Value).ToArray(); } } catch (Exception e) { Debug.WriteLine("QueryableStore Size or Filter function failure: {0}", e); } var total = pagedView.Length == 0 ? 0 : allRecords.Length + 1; var nextPageToken = currentTokenMeta.Next(pagedView.Length, total); var nextToken = p.Next(nextPageToken.ToString(), total, nextPageToken.HasMorePages()); return(new Continuation <T[]>(pagedView, nextToken)); }).Where(w => w.Records.Length > 0).Select(_ => _.Records); var storeMutationEvents = stream.Where(updateWhen); var view = CreateViewFromQuery(filterStream, token, queryFunc, scheduler); var viewPipeline = view.Select(_ => _.Records).CombineLatest(storeMutationEvents, (a, b) => localQueryFunc(view.Filter.Value(), view.Continuation.Value())).SelectMany(q => q); return(viewPipeline); }