public override async Task <QueryResponseCore> DrainAsync( int maxElements, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); // Note-2016-10-25-felixfan: Given what we support now, we should expect to return only 1 document. // Note-2019-07-11-brchon: We can return empty pages until all the documents are drained, // but then we will have to design a continuation token. double requestCharge = 0; long responseLengthBytes = 0; List <QueryPageDiagnostics> diagnosticsPages = new List <QueryPageDiagnostics>(); while (!this.Source.IsDone) { QueryResponseCore sourceResponse = await this.Source.DrainAsync(int.MaxValue, cancellationToken); if (!sourceResponse.IsSuccess) { return(sourceResponse); } requestCharge += sourceResponse.RequestCharge; responseLengthBytes += sourceResponse.ResponseLengthBytes; if (sourceResponse.Diagnostics != null) { diagnosticsPages.AddRange(sourceResponse.Diagnostics); } foreach (CosmosElement element in sourceResponse.CosmosElements) { RewrittenAggregateProjections rewrittenAggregateProjections = new RewrittenAggregateProjections( this.isValueAggregateQuery, element); this.singleGroupAggregator.AddValues(rewrittenAggregateProjections.Payload); } } List <CosmosElement> finalResult = new List <CosmosElement>(); CosmosElement aggregationResult = this.singleGroupAggregator.GetResult(); if (aggregationResult != null) { finalResult.Add(aggregationResult); } return(QueryResponseCore.CreateSuccess( result: finalResult, continuationToken: null, activityId: null, disallowContinuationTokenMessage: null, requestCharge: requestCharge, diagnostics: diagnosticsPages, responseLengthBytes: responseLengthBytes)); }
public override async Task <QueryResponseCore> DrainAsync( int maxElements, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); // Draining aggregates is broken down into two stages QueryResponseCore response; if (!this.Source.IsDone) { // Stage 1: // Drain the aggregates fully from all continuations and all partitions // And return empty pages in the meantime. QueryResponseCore sourceResponse = await this.Source.DrainAsync(int.MaxValue, cancellationToken); if (!sourceResponse.IsSuccess) { return(sourceResponse); } foreach (CosmosElement element in sourceResponse.CosmosElements) { RewrittenAggregateProjections rewrittenAggregateProjections = new RewrittenAggregateProjections( this.isValueAggregateQuery, element); this.singleGroupAggregator.AddValues(rewrittenAggregateProjections.Payload); } if (this.Source.IsDone) { response = this.GetFinalResponse(); } else { response = this.GetEmptyPage(sourceResponse); } } else { // Stage 2: // Return the final page after draining. response = this.GetFinalResponse(); } return(response); }
/// <summary> /// Drains at most 'maxElements' documents from the AggregateDocumentQueryExecutionComponent. /// </summary> /// <param name="maxElements">This value is ignored, since the aggregates are aggregated for you.</param> /// <param name="token">The cancellation token.</param> /// <returns>The aggregate result after all the continuations have been followed.</returns> /// <remarks> /// Note that this functions follows all continuations meaning that it won't return until all continuations are drained. /// This means that if you have a long running query this function will take a very long time to return. /// </remarks> public override async Task <QueryResponse> DrainAsync(int maxElements, CancellationToken token) { // Note-2016-10-25-felixfan: Given what we support now, we should expect to return only 1 document. // Note-2019-07-11-brchon: We can return empty pages until all the documents are drained, // but then we will have to design a continuation token. double requestCharge = 0; long responseLengthBytes = 0; List <Uri> replicaUris = new List <Uri>(); ClientSideRequestStatistics requestStatistics = new ClientSideRequestStatistics(); PartitionedQueryMetrics partitionedQueryMetrics = new PartitionedQueryMetrics(); ResourceType resourceType = ResourceType.Document; string containerRid = null; while (!this.IsDone) { QueryResponse result = await base.DrainAsync(int.MaxValue, token); if (!result.IsSuccessStatusCode) { return(result); } containerRid = result.QueryHeaders.ContainerRid; resourceType = result.QueryHeaders.ResourceType; requestCharge += result.Headers.RequestCharge; responseLengthBytes += result.ResponseLengthBytes; // DEVNOTE: Add when query metrics is supported // partitionedQueryMetrics += new PartitionedQueryMetrics(results.QueryMetrics); if (result.RequestStatistics != null) { replicaUris.AddRange(result.RequestStatistics.ContactedReplicas); } foreach (CosmosElement element in result.CosmosElements) { RewrittenAggregateProjections rewrittenAggregateProjections = new RewrittenAggregateProjections( this.isValueAggregateQuery, element); this.singleGroupAggregator.AddValues(rewrittenAggregateProjections.Payload); } } List <CosmosElement> finalResult = new List <CosmosElement>(); CosmosElement aggregationResult = this.singleGroupAggregator.GetResult(); if (aggregationResult != null) { finalResult.Add(aggregationResult); } // The replicaUris may have duplicates. requestStatistics.ContactedReplicas.AddRange(replicaUris); return(QueryResponse.CreateSuccess( result: finalResult, count: finalResult.Count, responseLengthBytes: responseLengthBytes, responseHeaders: new CosmosQueryResponseMessageHeaders( continauationToken: null, disallowContinuationTokenMessage: null, resourceType: resourceType, containerRid: containerRid) { RequestCharge = requestCharge }, queryMetrics: this.GetQueryMetrics())); }