Esempio n. 1
0
        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);
            });
        }