/// <summary> /// Creates a CosmosPipelinedItemQueryExecutionContext. /// </summary> /// <param name="constructorParams">The parameters for constructing the base class.</param> /// <param name="collectionRid">The collection rid.</param> /// <param name="partitionedQueryExecutionInfo">The partitioned query execution info.</param> /// <param name="partitionKeyRanges">The partition key ranges.</param> /// <param name="initialPageSize">The initial page size.</param> /// <param name="requestContinuation">The request continuation.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>A task to await on, which in turn returns a CosmosPipelinedItemQueryExecutionContext.</returns> public static async Task <IDocumentQueryExecutionContext> CreateAsync( CosmosQueryContext constructorParams, string collectionRid, PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, List <PartitionKeyRange> partitionKeyRanges, int initialPageSize, string requestContinuation, CancellationToken cancellationToken) { DefaultTrace.TraceInformation( string.Format( CultureInfo.InvariantCulture, "{0}, CorrelatedActivityId: {1} | Pipelined~Context.CreateAsync", DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture), constructorParams.CorrelatedActivityId)); Func <string, Task <IDocumentQueryExecutionComponent> > createComponentFunc; QueryInfo queryInfo = partitionedQueryExecutionInfo.QueryInfo; if (queryInfo.HasOrderBy) { createComponentFunc = async(continuationToken) => { CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams initParams = new CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams( collectionRid, partitionedQueryExecutionInfo, partitionKeyRanges, initialPageSize, continuationToken); return(await CosmosOrderByItemQueryExecutionContext.CreateAsync( constructorParams, initParams, cancellationToken)); }; } else { createComponentFunc = async(continuationToken) => { CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams initParams = new CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams( collectionRid, partitionedQueryExecutionInfo, partitionKeyRanges, initialPageSize, continuationToken); return(await CosmosParallelItemQueryExecutionContext.CreateAsync( constructorParams, initParams, cancellationToken)); }; } if (queryInfo.HasAggregates) { Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc; createComponentFunc = async(continuationToken) => { return(await AggregateDocumentQueryExecutionComponent.CreateAsync( queryInfo.Aggregates, continuationToken, createSourceCallback)); }; } if (queryInfo.HasDistinct) { Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc; createComponentFunc = async(continuationToken) => { return(await DistinctDocumentQueryExecutionComponent.CreateAsync( continuationToken, createSourceCallback, queryInfo.DistinctType)); }; } if (queryInfo.HasOffset) { if (!constructorParams.QueryRequestOptions.EnableCrossPartitionSkipTake) { throw new ArgumentException("Cross Partition OFFSET / LIMIT is not supported."); } Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc; createComponentFunc = async(continuationToken) => { return(await SkipDocumentQueryExecutionComponent.CreateAsync( queryInfo.Offset.Value, continuationToken, createSourceCallback)); }; } if (queryInfo.HasLimit) { if (!constructorParams.QueryRequestOptions.EnableCrossPartitionSkipTake) { throw new ArgumentException("Cross Partition OFFSET / LIMIT is not supported."); } Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc; createComponentFunc = async(continuationToken) => { return(await TakeDocumentQueryExecutionComponent.CreateLimitDocumentQueryExecutionComponentAsync( queryInfo.Limit.Value, continuationToken, createSourceCallback)); }; } if (queryInfo.HasTop) { Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc; createComponentFunc = async(continuationToken) => { return(await TakeDocumentQueryExecutionComponent.CreateTopDocumentQueryExecutionComponentAsync( queryInfo.Top.Value, continuationToken, createSourceCallback)); }; } return(new CosmosPipelinedItemQueryExecutionContext( await createComponentFunc(requestContinuation), initialPageSize)); }
public async Task <CosmosQueryExecutionContext> CreateSpecializedDocumentQueryExecutionContextAsync( CosmosQueryContext cosmosQueryContext, PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, List <PartitionKeyRange> targetRanges, string collectionRid, CancellationToken cancellationToken) { if (!string.IsNullOrEmpty(partitionedQueryExecutionInfo.QueryInfo?.RewrittenQuery)) { cosmosQueryContext.SqlQuerySpec = new SqlQuerySpec( partitionedQueryExecutionInfo.QueryInfo.RewrittenQuery, cosmosQueryContext.SqlQuerySpec.Parameters); } // Figure out the optimal page size. long initialPageSize = cosmosQueryContext.QueryRequestOptions.MaxItemCount.GetValueOrDefault(ParallelQueryConfig.GetConfig().ClientInternalPageSize); if (initialPageSize < -1 || initialPageSize == 0) { throw new BadRequestException(string.Format(CultureInfo.InvariantCulture, "Invalid MaxItemCount {0}", initialPageSize)); } QueryInfo queryInfo = partitionedQueryExecutionInfo.QueryInfo; bool getLazyFeedResponse = queryInfo.HasTop; // We need to compute the optimal initial page size for order-by queries if (queryInfo.HasOrderBy) { int top; if (queryInfo.HasTop && (top = partitionedQueryExecutionInfo.QueryInfo.Top.Value) > 0) { // All partitions should initially fetch about 1/nth of the top value. long pageSizeWithTop = (long)Math.Min( Math.Ceiling(top / (double)targetRanges.Count) * PageSizeFactorForTop, top); if (initialPageSize > 0) { initialPageSize = Math.Min(pageSizeWithTop, initialPageSize); } else { initialPageSize = pageSizeWithTop; } } else if (cosmosQueryContext.IsContinuationExpected) { if (initialPageSize < 0) { if (cosmosQueryContext.QueryRequestOptions.MaxBufferedItemCount.HasValue) { // Max of what the user is willing to buffer and the default (note this is broken if MaxBufferedItemCount = -1) initialPageSize = Math.Max(cosmosQueryContext.QueryRequestOptions.MaxBufferedItemCount.Value, ParallelQueryConfig.GetConfig().DefaultMaximumBufferSize); } else { initialPageSize = ParallelQueryConfig.GetConfig().DefaultMaximumBufferSize; } } initialPageSize = (long)Math.Min( Math.Ceiling(initialPageSize / (double)targetRanges.Count) * PageSizeFactorForTop, initialPageSize); } } Debug.Assert(initialPageSize > 0 && initialPageSize <= int.MaxValue, string.Format(CultureInfo.InvariantCulture, "Invalid MaxItemCount {0}", initialPageSize)); return(await PipelinedDocumentQueryExecutionContext.CreateAsync( cosmosQueryContext, collectionRid, partitionedQueryExecutionInfo, targetRanges, (int)initialPageSize, this.InitialUserContinuationToken, cancellationToken)); }
private static async Task <PipelinedDocumentQueryExecutionContext> CreateHelperAsync( QueryInfo queryInfo, int initialPageSize, string requestContinuation, Func <string, Task <IDocumentQueryExecutionComponent> > createOrderByQueryExecutionContext, Func <string, Task <IDocumentQueryExecutionComponent> > createParallelQueryExecutionContext) { Func <string, Task <IDocumentQueryExecutionComponent> > createComponentFunc; if (queryInfo.HasOrderBy) { createComponentFunc = createOrderByQueryExecutionContext; } else { createComponentFunc = createParallelQueryExecutionContext; } if (queryInfo.HasAggregates) { Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc; createComponentFunc = async(continuationToken) => { return(await AggregateDocumentQueryExecutionComponent.CreateAsync( queryInfo.Aggregates, continuationToken, createSourceCallback)); }; } if (queryInfo.HasDistinct) { Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc; createComponentFunc = async(continuationToken) => { return(await DistinctDocumentQueryExecutionComponent.CreateAsync( continuationToken, createSourceCallback, queryInfo.DistinctType)); }; } if (queryInfo.HasOffset) { Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc; createComponentFunc = async(continuationToken) => { return(await SkipDocumentQueryExecutionComponent.CreateAsync( queryInfo.Offset.Value, continuationToken, createSourceCallback)); }; } if (queryInfo.HasLimit) { Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc; createComponentFunc = async(continuationToken) => { return(await TakeDocumentQueryExecutionComponent.CreateLimitDocumentQueryExecutionComponentAsync( queryInfo.Limit.Value, continuationToken, createSourceCallback)); }; } if (queryInfo.HasTop) { Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc; createComponentFunc = async(continuationToken) => { return(await TakeDocumentQueryExecutionComponent.CreateTopDocumentQueryExecutionComponentAsync( queryInfo.Top.Value, continuationToken, createSourceCallback)); }; } return(new PipelinedDocumentQueryExecutionContext( await createComponentFunc(requestContinuation), initialPageSize)); }
public static async Task <PipelinedDocumentQueryExecutionContext> CreateAsync( IDocumentQueryClient client, ResourceType resourceTypeEnum, Type resourceType, Expression expression, FeedOptions feedOptions, string resourceLink, string collectionRid, PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, List <PartitionKeyRange> targetRanges, int initialPageSize, bool isContinuationExpected, bool getLazyFeedResponse, CancellationToken token, Guid correlatedActivityId) { DefaultTrace.TraceInformation( string.Format( CultureInfo.InvariantCulture, "{0}, CorrelatedActivityId: {1} | Pipelined~Context.CreateAsync", DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture), correlatedActivityId)); Func <string, Task <IDocumentQueryExecutionComponent> > createComponentFunc; QueryInfo queryInfo = partitionedQueryExecutionInfo.QueryInfo; if (queryInfo.HasOrderBy) { createComponentFunc = async(requestContinuation) => { return(await OrderByDocumentQueryExecutionContext.CreateAsync( client, resourceTypeEnum, resourceType, expression, feedOptions, resourceLink, collectionRid, partitionedQueryExecutionInfo, targetRanges, initialPageSize, isContinuationExpected, getLazyFeedResponse, requestContinuation, token, correlatedActivityId)); }; } else { createComponentFunc = async(requestContinuation) => { return(await ParallelDocumentQueryExecutionContext.CreateAsync( client, resourceTypeEnum, resourceType, expression, feedOptions, resourceLink, collectionRid, partitionedQueryExecutionInfo, targetRanges, initialPageSize, isContinuationExpected, getLazyFeedResponse, requestContinuation, token, correlatedActivityId)); }; } if (queryInfo.HasAggregates) { Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc; createComponentFunc = async(requestContinuation) => { return(await AggregateDocumentQueryExecutionComponent.CreateAsync( queryInfo.Aggregates, requestContinuation, createSourceCallback)); }; } if (queryInfo.HasDistinct) { Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc; createComponentFunc = async(requestContinuation) => { return(await DistinctDocumentQueryExecutionComponent.CreateAsync( requestContinuation, createSourceCallback, queryInfo.DistinctType)); }; } if (queryInfo.HasTop) { Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc; createComponentFunc = async(requestContinuation) => { return(await TopDocumentQueryExecutionComponent.CreateAsync( queryInfo.Top.Value, requestContinuation, createSourceCallback)); }; } int actualPageSize = feedOptions.MaxItemCount.GetValueOrDefault(ParallelQueryConfig.GetConfig().ClientInternalPageSize); // If this contract changes, make the corresponding change in MongoDocumentClient.QueryInternalAsync if (actualPageSize == -1) { actualPageSize = int.MaxValue; } return(new PipelinedDocumentQueryExecutionContext( await createComponentFunc(feedOptions.RequestContinuation), Math.Min(actualPageSize, queryInfo.Top.GetValueOrDefault(actualPageSize)), correlatedActivityId)); }
private static async Task <PipelinedDocumentQueryExecutionContext> CreateHelperAsync( QueryInfo queryInfo, int initialPageSize, string requestContinuation, bool allowGroupBy, Func <string, Task <IDocumentQueryExecutionComponent> > createOrderByQueryExecutionContext, Func <string, Task <IDocumentQueryExecutionComponent> > createParallelQueryExecutionContext) { Func <string, Task <IDocumentQueryExecutionComponent> > createComponentFunc; if (queryInfo.HasOrderBy) { createComponentFunc = createOrderByQueryExecutionContext; } else { createComponentFunc = createParallelQueryExecutionContext; } if (queryInfo.HasAggregates && !queryInfo.HasGroupBy) { Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc; createComponentFunc = async(continuationToken) => { return(await AggregateDocumentQueryExecutionComponent.CreateAsync( queryInfo.Aggregates, queryInfo.GroupByAliasToAggregateType, queryInfo.HasSelectValue, continuationToken, createSourceCallback)); }; } if (queryInfo.HasDistinct) { Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc; createComponentFunc = async(continuationToken) => { return(await DistinctDocumentQueryExecutionComponent.CreateAsync( continuationToken, createSourceCallback, queryInfo.DistinctType)); }; } if (queryInfo.HasGroupBy) { if (!allowGroupBy) { throw new ArgumentException("Cross Partition GROUP BY is not supported."); } Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc; createComponentFunc = async(continuationToken) => { return(await GroupByDocumentQueryExecutionComponent.CreateAsync( continuationToken, createSourceCallback, queryInfo.GroupByAliasToAggregateType, queryInfo.HasSelectValue)); }; } if (queryInfo.HasOffset) { Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc; createComponentFunc = async(continuationToken) => { return(await SkipDocumentQueryExecutionComponent.CreateAsync( queryInfo.Offset.Value, continuationToken, createSourceCallback)); }; } if (queryInfo.HasLimit) { Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc; createComponentFunc = async(continuationToken) => { return(await TakeDocumentQueryExecutionComponent.CreateLimitDocumentQueryExecutionComponentAsync( queryInfo.Limit.Value, continuationToken, createSourceCallback)); }; } if (queryInfo.HasTop) { Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback = createComponentFunc; createComponentFunc = async(continuationToken) => { return(await TakeDocumentQueryExecutionComponent.CreateTopDocumentQueryExecutionComponentAsync( queryInfo.Top.Value, continuationToken, createSourceCallback)); }; } return(new PipelinedDocumentQueryExecutionContext( await createComponentFunc(requestContinuation), initialPageSize)); }
/// <summary> /// Creates a CosmosPipelinedItemQueryExecutionContext. /// </summary> /// <param name="constructorParams">The parameters for constructing the base class.</param> /// <param name="collectionRid">The collection rid.</param> /// <param name="partitionedQueryExecutionInfo">The partitioned query execution info.</param> /// <param name="partitionKeyRanges">The partition key ranges.</param> /// <param name="initialPageSize">The initial page size.</param> /// <param name="requestContinuation">The request continuation.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>A task to await on, which in turn returns a CosmosPipelinedItemQueryExecutionContext.</returns> public static async Task <CosmosQueryExecutionContext> CreateAsync( CosmosQueryContext constructorParams, string collectionRid, PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, List <PartitionKeyRange> partitionKeyRanges, int initialPageSize, string requestContinuation, CancellationToken cancellationToken) { DefaultTrace.TraceInformation( string.Format( CultureInfo.InvariantCulture, "{0}, CorrelatedActivityId: {1} | Pipelined~Context.CreateAsync", DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture), constructorParams.CorrelatedActivityId)); QueryInfo queryInfo = partitionedQueryExecutionInfo.QueryInfo; int actualPageSize = initialPageSize; if (queryInfo.HasGroupBy) { initialPageSize = int.MaxValue; constructorParams.QueryRequestOptions.MaxItemCount = int.MaxValue; } Func <string, Task <IDocumentQueryExecutionComponent> > createOrderByComponentFunc = async(continuationToken) => { CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams initParams = new CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams( collectionRid, partitionedQueryExecutionInfo, partitionKeyRanges, initialPageSize, continuationToken); return(await CosmosOrderByItemQueryExecutionContext.CreateAsync( constructorParams, initParams, cancellationToken)); }; Func <string, Task <IDocumentQueryExecutionComponent> > createParallelComponentFunc = async(continuationToken) => { CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams initParams = new CosmosCrossPartitionQueryExecutionContext.CrossPartitionInitParams( collectionRid, partitionedQueryExecutionInfo, partitionKeyRanges, initialPageSize, continuationToken); return(await CosmosParallelItemQueryExecutionContext.CreateAsync( constructorParams, initParams, cancellationToken)); }; return((CosmosQueryExecutionContext)await PipelinedDocumentQueryExecutionContext.CreateHelperAsync( partitionedQueryExecutionInfo.QueryInfo, initialPageSize, requestContinuation, constructorParams.QueryRequestOptions.EnableGroupBy, createOrderByComponentFunc, createParallelComponentFunc)); }
public static async Task <IDocumentQueryExecutionContext> CreateSpecializedDocumentQueryExecutionContext( IDocumentQueryClient client, ResourceType resourceTypeEnum, Type resourceType, Expression expression, FeedOptions feedOptions, string resourceLink, bool isContinuationExpected, PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, List <PartitionKeyRange> targetRanges, string collectionRid, CancellationToken token, Guid correlatedActivityId) { long initialPageSize = feedOptions.MaxItemCount.GetValueOrDefault(ParallelQueryConfig.GetConfig().ClientInternalPageSize); if (initialPageSize < -1 || initialPageSize == 0) { throw new BadRequestException(string.Format(CultureInfo.InvariantCulture, "Invalid MaxItemCount {0}", initialPageSize)); } QueryInfo queryInfo = partitionedQueryExecutionInfo.QueryInfo; bool getLazyFeedResponse = queryInfo.HasTop; // We need to compute the optimal initial page size for order-by queries if (queryInfo.HasOrderBy) { int top; if (queryInfo.HasTop && (top = partitionedQueryExecutionInfo.QueryInfo.Top.Value) > 0) { // All partitions should initially fetch about 1/nth of the top value. long pageSizeWithTop = (long)Math.Min( Math.Ceiling(top / (double)targetRanges.Count) * PageSizeFactorForTop, top); if (initialPageSize > 0) { initialPageSize = Math.Min(pageSizeWithTop, initialPageSize); } else { initialPageSize = pageSizeWithTop; } } else if (isContinuationExpected) { if (initialPageSize < 0) { // Max of what the user is willing to buffer and the default (note this is broken if MaxBufferedItemCount = -1) initialPageSize = (long)Math.Max(feedOptions.MaxBufferedItemCount, ParallelQueryConfig.GetConfig().DefaultMaximumBufferSize); } initialPageSize = (long)Math.Min( Math.Ceiling(initialPageSize / (double)targetRanges.Count) * PageSizeFactorForTop, initialPageSize); } } Debug.Assert(initialPageSize > 0 && initialPageSize <= int.MaxValue, string.Format(CultureInfo.InvariantCulture, "Invalid MaxItemCount {0}", initialPageSize)); return(await PipelinedDocumentQueryExecutionContext.CreateAsync( client, resourceTypeEnum, resourceType, expression, feedOptions, resourceLink, collectionRid, partitionedQueryExecutionInfo, targetRanges, (int)initialPageSize, isContinuationExpected, getLazyFeedResponse, token, correlatedActivityId)); }