public CrossPartitionRangePageAsyncEnumerator( IFeedRangeProvider feedRangeProvider, CreatePartitionRangePageAsyncEnumerator <TPage, TState> createPartitionRangeEnumerator, IComparer <PartitionRangePageAsyncEnumerator <TPage, TState> > comparer, int?maxConcurrency, CancellationToken cancellationToken, CrossPartitionState <TState> state = default) { if (comparer == null) { throw new ArgumentNullException(nameof(comparer)); } this.feedRangeProvider = feedRangeProvider ?? throw new ArgumentNullException(nameof(feedRangeProvider)); this.createPartitionRangeEnumerator = createPartitionRangeEnumerator ?? throw new ArgumentNullException(nameof(createPartitionRangeEnumerator)); this.cancellationToken = cancellationToken; this.lazyEnumerators = new AsyncLazy <PriorityQueue <PartitionRangePageAsyncEnumerator <TPage, TState> > >(async(CancellationToken token) => { IReadOnlyList <(PartitionKeyRange, TState)> rangeAndStates; if (state != default) { rangeAndStates = state.Value; } else { // Fan out to all partitions with default state IEnumerable <PartitionKeyRange> ranges = await feedRangeProvider.GetFeedRangesAsync(token); List <(PartitionKeyRange, TState)> rangesAndStatesBuilder = new List <(PartitionKeyRange, TState)>(); foreach (PartitionKeyRange range in ranges) { rangesAndStatesBuilder.Add((range, default)); } rangeAndStates = rangesAndStatesBuilder; } List <BufferedPartitionRangePageAsyncEnumerator <TPage, TState> > bufferedEnumerators = rangeAndStates .Select(rangeAndState => { PartitionRangePageAsyncEnumerator <TPage, TState> enumerator = createPartitionRangeEnumerator(rangeAndState.Item1, rangeAndState.Item2); BufferedPartitionRangePageAsyncEnumerator <TPage, TState> bufferedEnumerator = new BufferedPartitionRangePageAsyncEnumerator <TPage, TState>(enumerator, cancellationToken); return(bufferedEnumerator); }) .ToList(); if (maxConcurrency.HasValue) { await ParallelPrefetch.PrefetchInParallelAsync(bufferedEnumerators, maxConcurrency.Value, token); } PriorityQueue <PartitionRangePageAsyncEnumerator <TPage, TState> > enumerators = new PriorityQueue <PartitionRangePageAsyncEnumerator <TPage, TState> >( bufferedEnumerators, comparer); return(enumerators); }); }
public CrossPartitionRangePageAsyncEnumerator( IFeedRangeProvider feedRangeProvider, CreatePartitionRangePageAsyncEnumerator <TPage, TState> createPartitionRangeEnumerator, IComparer <PartitionRangePageAsyncEnumerator <TPage, TState> > comparer, int?maxConcurrency, CancellationToken cancellationToken, CrossFeedRangeState <TState> state = default) { this.feedRangeProvider = feedRangeProvider ?? throw new ArgumentNullException(nameof(feedRangeProvider)); this.createPartitionRangeEnumerator = createPartitionRangeEnumerator ?? throw new ArgumentNullException(nameof(createPartitionRangeEnumerator)); this.cancellationToken = cancellationToken; this.lazyEnumerators = new AsyncLazy <IQueue <PartitionRangePageAsyncEnumerator <TPage, TState> > >(async(ITrace trace, CancellationToken token) => { ReadOnlyMemory <FeedRangeState <TState> > rangeAndStates; if (state != default) { rangeAndStates = state.Value; } else { // Fan out to all partitions with default state List <FeedRangeEpk> ranges = await feedRangeProvider.GetFeedRangesAsync(trace, token); List <FeedRangeState <TState> > rangesAndStatesBuilder = new List <FeedRangeState <TState> >(ranges.Count); foreach (FeedRangeInternal range in ranges) { rangesAndStatesBuilder.Add(new FeedRangeState <TState>(range, default)); } rangeAndStates = rangesAndStatesBuilder.ToArray(); } List <BufferedPartitionRangePageAsyncEnumerator <TPage, TState> > bufferedEnumerators = new List <BufferedPartitionRangePageAsyncEnumerator <TPage, TState> >(rangeAndStates.Length); for (int i = 0; i < rangeAndStates.Length; i++) { FeedRangeState <TState> feedRangeState = rangeAndStates.Span[i]; PartitionRangePageAsyncEnumerator <TPage, TState> enumerator = createPartitionRangeEnumerator(feedRangeState); BufferedPartitionRangePageAsyncEnumerator <TPage, TState> bufferedEnumerator = new BufferedPartitionRangePageAsyncEnumerator <TPage, TState>(enumerator, cancellationToken); bufferedEnumerators.Add(bufferedEnumerator); } if (maxConcurrency.HasValue) { await ParallelPrefetch.PrefetchInParallelAsync(bufferedEnumerators, maxConcurrency.Value, trace, token); } IQueue <PartitionRangePageAsyncEnumerator <TPage, TState> > queue; if (comparer == null) { queue = new QueueWrapper <PartitionRangePageAsyncEnumerator <TPage, TState> >( new Queue <PartitionRangePageAsyncEnumerator <TPage, TState> >(bufferedEnumerators)); } else { queue = new PriorityQueueWrapper <PartitionRangePageAsyncEnumerator <TPage, TState> >( new PriorityQueue <PartitionRangePageAsyncEnumerator <TPage, TState> >( bufferedEnumerators, comparer)); } return(queue); }); }