public override async Task <ResponseMessage> ReadNextAsync(CancellationToken cancellationToken = default) { CosmosDiagnosticsContext diagnostics = new CosmosDiagnosticsContext(); using (diagnostics.CreateScope("QueryReadNextAsync")) { // This catches exception thrown by the pipeline and converts it to QueryResponse QueryResponseCore responseCore = await this.cosmosQueryExecutionContext.ExecuteNextAsync(cancellationToken); CosmosQueryContext cosmosQueryContext = this.cosmosQueryContext; foreach (QueryPageDiagnostics queryPage in responseCore.Diagnostics) { diagnostics.Summary.Append(queryPage.DiagnosticsContext.Summary); diagnostics.AddDiagnosticsInternal(queryPage); } QueryResponse queryResponse; if (responseCore.IsSuccess) { queryResponse = QueryResponse.CreateSuccess( result: responseCore.CosmosElements, count: responseCore.CosmosElements.Count, responseLengthBytes: responseCore.ResponseLengthBytes, diagnostics: diagnostics, serializationOptions: this.cosmosSerializationFormatOptions, responseHeaders: new CosmosQueryResponseMessageHeaders( responseCore.ContinuationToken, responseCore.DisallowContinuationTokenMessage, cosmosQueryContext.ResourceTypeEnum, cosmosQueryContext.ContainerResourceId) { RequestCharge = responseCore.RequestCharge, ActivityId = responseCore.ActivityId, SubStatusCode = responseCore.SubStatusCode ?? Documents.SubStatusCodes.Unknown }); } else { queryResponse = QueryResponse.CreateFailure( statusCode: responseCore.StatusCode, error: null, errorMessage: responseCore.ErrorMessage, requestMessage: null, diagnostics: diagnostics, responseHeaders: new CosmosQueryResponseMessageHeaders( responseCore.ContinuationToken, responseCore.DisallowContinuationTokenMessage, cosmosQueryContext.ResourceTypeEnum, cosmosQueryContext.ContainerResourceId) { RequestCharge = responseCore.RequestCharge, ActivityId = responseCore.ActivityId, SubStatusCode = responseCore.SubStatusCode ?? Documents.SubStatusCodes.Unknown }); } return(queryResponse); } }
public void ExceptionFromTryCatchWithCosmosException() { CosmosException cosmosException; try { throw CosmosExceptionFactory.CreateBadRequestException("InternalServerTestMessage", new Headers()); } catch (CosmosException ce) { cosmosException = ce; } TryCatch <object> tryCatch = this.QueryExceptionHelper(cosmosException); QueryResponseCore queryResponse = QueryResponseFactory.CreateFromException(tryCatch.Exception); Assert.AreEqual(HttpStatusCode.BadRequest, queryResponse.StatusCode); Assert.IsNotNull(queryResponse.CosmosException); // Should preserve the original stack trace. string exceptionMessage = queryResponse.CosmosException.ToString(); Assert.IsTrue(exceptionMessage.Contains("InternalServerTestMessage")); Assert.IsFalse(exceptionMessage.Contains(nameof(QueryExceptionHelper))); }
public override async Task <ResponseMessage> ReadNextAsync(CancellationToken cancellationToken = default) { CosmosDiagnosticsContext diagnostics = CosmosDiagnosticsContext.Create(this.requestOptions); using (diagnostics.GetOverallScope()) { // This catches exception thrown by the pipeline and converts it to QueryResponse QueryResponseCore responseCore = await this.cosmosQueryExecutionContext.ExecuteNextAsync(cancellationToken); // This swaps the diagnostics in the context. This shows all the page reads between the previous ReadNextAsync and the current ReadNextAsync diagnostics.AddDiagnosticsInternal(this.cosmosQueryContext.GetAndResetDiagnostics()); if (responseCore.IsSuccess) { List <CosmosElement> decryptedCosmosElements = null; if (this.clientContext.ClientOptions.Encryptor != null) { decryptedCosmosElements = await this.GetDecryptedElementResponseAsync(responseCore.CosmosElements, diagnostics, cancellationToken); } return(QueryResponse.CreateSuccess( result: decryptedCosmosElements ?? responseCore.CosmosElements, count: responseCore.CosmosElements.Count, responseLengthBytes: responseCore.ResponseLengthBytes, diagnostics: diagnostics, serializationOptions: this.cosmosSerializationFormatOptions, responseHeaders: new CosmosQueryResponseMessageHeaders( responseCore.ContinuationToken, responseCore.DisallowContinuationTokenMessage, this.cosmosQueryContext.ResourceTypeEnum, this.cosmosQueryContext.ContainerResourceId) { RequestCharge = responseCore.RequestCharge, ActivityId = responseCore.ActivityId, SubStatusCode = responseCore.SubStatusCode ?? Documents.SubStatusCodes.Unknown })); } if (responseCore.CosmosException != null) { return(responseCore.CosmosException.ToCosmosResponseMessage(null)); } return(QueryResponse.CreateFailure( statusCode: responseCore.StatusCode, cosmosException: responseCore.CosmosException, requestMessage: null, diagnostics: diagnostics, responseHeaders: new CosmosQueryResponseMessageHeaders( responseCore.ContinuationToken, responseCore.DisallowContinuationTokenMessage, this.cosmosQueryContext.ResourceTypeEnum, this.cosmosQueryContext.ContainerResourceId) { RequestCharge = responseCore.RequestCharge, ActivityId = responseCore.ActivityId, SubStatusCode = responseCore.SubStatusCode ?? Documents.SubStatusCodes.Unknown, })); } }
internal static QueryResponseCore CreateSuccess( IReadOnlyList <CosmosElement> result, double requestCharge, string activityId, string queryMetricsText, IReadOnlyDictionary <string, QueryMetrics> queryMetrics, ClientSideRequestStatistics requestStatistics, long responseLengthBytes, string disallowContinuationTokenMessage, string continuationToken) { QueryResponseCore cosmosQueryResponse = new QueryResponseCore( result: result, isSuccess: true, statusCode: HttpStatusCode.OK, requestCharge: requestCharge, activityId: activityId, queryMetricsText: queryMetricsText, queryMetrics: queryMetrics, requestStatistics: requestStatistics, responseLengthBytes: responseLengthBytes, disallowContinuationTokenMessage: disallowContinuationTokenMessage, continuationToken: continuationToken, errorMessage: null, subStatusCode: null); return(cosmosQueryResponse); }
internal static QueryResponseCore CreateFailure( HttpStatusCode statusCode, SubStatusCodes?subStatusCodes, string errorMessage, double requestCharge, string activityId, string queryMetricsText, IReadOnlyDictionary <string, QueryMetrics> queryMetrics) { QueryResponseCore cosmosQueryResponse = new QueryResponseCore( result: QueryResponseCore.EmptyList, isSuccess: false, statusCode: statusCode, requestCharge: requestCharge, activityId: activityId, queryMetricsText: queryMetricsText, queryMetrics: queryMetrics, requestStatistics: null, responseLengthBytes: 0, disallowContinuationTokenMessage: null, continuationToken: null, errorMessage: errorMessage, subStatusCode: subStatusCodes); return(cosmosQueryResponse); }
public void QueryException() { QueryException queryException = new MalformedContinuationTokenException(); QueryResponseCore queryResponse = QueryResponseFactory.CreateFromException(queryException); Assert.AreEqual(HttpStatusCode.BadRequest, queryResponse.StatusCode); Assert.IsNotNull(queryResponse.ErrorMessage); }
public void DocumentClientException() { Documents.DocumentClientException documentClientException = new Documents.RequestRateTooLargeException("asdf"); QueryResponseCore queryResponse = QueryResponseFactory.CreateFromException(documentClientException); Assert.AreEqual((HttpStatusCode)429, queryResponse.StatusCode); Assert.IsNotNull(queryResponse.ErrorMessage); }
public void CosmosException() { CosmosException cosmosException = CosmosExceptionFactory.CreateBadRequestException( message: "asdf"); QueryResponseCore queryResponse = QueryResponseFactory.CreateFromException(cosmosException); Assert.AreEqual(HttpStatusCode.BadRequest, queryResponse.StatusCode); Assert.IsNotNull(queryResponse.CosmosException); }
public void ExceptionFromTryCatch() { TryCatch <object> tryCatch = this.QueryExceptionHelper(new MalformedContinuationTokenException("TestMessage")); QueryResponseCore queryResponse = QueryResponseFactory.CreateFromException(tryCatch.Exception); Assert.AreEqual(HttpStatusCode.BadRequest, queryResponse.StatusCode); Assert.IsNotNull(queryResponse.CosmosException); Assert.IsTrue(queryResponse.CosmosException.ToString().Contains("TestMessage")); Assert.IsTrue(queryResponse.CosmosException.ToString().Contains(nameof(QueryExceptionHelper)), queryResponse.CosmosException.ToString()); }
public void ExceptionFromTryCatch() { QueryException queryException = new MalformedContinuationTokenException(); TryCatch <object> tryCatch = TryCatch <object> .FromException(queryException); QueryResponseCore queryResponse = QueryResponseFactory.CreateFromException(tryCatch.Exception); Assert.AreEqual(HttpStatusCode.BadRequest, queryResponse.StatusCode); Assert.IsNotNull(queryResponse.ErrorMessage); Assert.IsTrue(queryResponse.ErrorMessage.Contains(nameof(ExceptionFromTryCatch))); }
/// <summary> /// Gets the next page of results from this context. /// </summary> /// <param name="token">The cancellation token.</param> /// <returns>A task to await on that in turn returns a DoucmentFeedResponse of results.</returns> public async Task <DocumentFeedResponse <CosmosElement> > ExecuteNextFeedResponseAsync(CancellationToken token) { QueryResponseCore feedResponse = await this.ExecuteNextAsync(token); return(new DocumentFeedResponse <CosmosElement>( result: feedResponse.CosmosElements, count: feedResponse.CosmosElements.Count, responseHeaders: new DictionaryNameValueCollection(), useETagAsContinuation: false, queryMetrics: feedResponse.QueryMetrics, requestStats: feedResponse.RequestStatistics, disallowContinuationTokenMessage: feedResponse.DisallowContinuationTokenMessage, responseLengthBytes: feedResponse.ResponseLengthBytes)); }
public override async Task <QueryResponseCore> DrainAsync(int maxElements, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); // In order to maintain the continuation token for the user we must drain with a few constraints // 1) We fully drain from the left most partition before moving on to the next partition // 2) We drain only full pages from the document producer so we aren't left with a partial page // otherwise we would need to add to the continuation token how many items to skip over on that page. // Only drain from the leftmost (current) document producer tree ItemProducerTree currentItemProducerTree = this.PopCurrentItemProducerTree(); List <CosmosElement> results = new List <CosmosElement>(); try { (bool gotNextPage, QueryResponseCore? failureResponse) = await currentItemProducerTree.TryMoveNextPageAsync(cancellationToken); if (failureResponse != null) { return(failureResponse.Value); } if (gotNextPage) { int itemsLeftInCurrentPage = currentItemProducerTree.ItemsLeftInCurrentPage; // Only drain full pages or less if this is a top query. currentItemProducerTree.TryMoveNextDocumentWithinPage(); int numberOfItemsToDrain = Math.Min(itemsLeftInCurrentPage, maxElements); for (int i = 0; i < numberOfItemsToDrain; i++) { results.Add(currentItemProducerTree.Current); currentItemProducerTree.TryMoveNextDocumentWithinPage(); } } } finally { this.PushCurrentItemProducerTree(currentItemProducerTree); } return(QueryResponseCore.CreateSuccess( result: results, requestCharge: this.requestChargeTracker.GetAndResetCharge(), activityId: null, responseLengthBytes: this.GetAndResetResponseLengthBytes(), disallowContinuationTokenMessage: null, continuationToken: this.ContinuationToken, diagnostics: this.GetAndResetDiagnostics())); }
/// <summary> /// Drains documents from this component. This has the common drain logic for each implementation. /// </summary> /// <param name="maxElements">The maximum number of documents to drain.</param> /// <param name="cancellationToken">The cancellation token to cancel tasks.</param> /// <returns>A task that when awaited on returns a feed response.</returns> public override async Task <QueryResponseCore> DrainAsync(int maxElements, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); // The initialization or previous Drain Async failed. Just return the failure. if (this.FailureResponse != null) { this.Stop(); QueryResponseCore failure = this.FailureResponse.Value; this.FailureResponse = null; return(failure); } // Drain the results. If there is no results and a failure then return the failure. IReadOnlyList <CosmosElement> results = await this.InternalDrainAsync(maxElements, cancellationToken); if ((results == null || results.Count == 0) && this.FailureResponse != null) { this.Stop(); QueryResponseCore failure = this.FailureResponse.Value; this.FailureResponse = null; return(failure); } string continuation = this.ContinuationToken; if (continuation == "[]") { throw new InvalidOperationException("Somehow a document query execution context returned an empty array of continuations."); } this.SetQueryMetrics(); return(QueryResponseCore.CreateSuccess( result: results, requestCharge: this.requestChargeTracker.GetAndResetCharge(), activityId: null, queryMetricsText: null, disallowContinuationTokenMessage: null, continuationToken: continuation, queryMetrics: this.GetQueryMetrics(), requestStatistics: null, responseLengthBytes: this.GetAndResetResponseLengthBytes())); }
/// <summary> /// Gets the next page of results from this context. /// </summary> /// <param name="token">The cancellation token.</param> /// <returns>A task to await on that in turn returns a DoucmentFeedResponse of results.</returns> public override async Task <QueryResponseCore> ExecuteNextAsync(CancellationToken token) { try { QueryResponseCore queryResponse = await this.component.DrainAsync(this.actualPageSize, token); if (!queryResponse.IsSuccess) { this.component.Stop(); return(queryResponse); } string updatedContinuationToken; if (queryResponse.DisallowContinuationTokenMessage == null) { if (queryResponse.ContinuationToken != null) { updatedContinuationToken = new PipelineContinuationTokenV0(queryResponse.ContinuationToken).ToString(); } else { updatedContinuationToken = null; } } else { updatedContinuationToken = null; } return(QueryResponseCore.CreateSuccess( result: queryResponse.CosmosElements, continuationToken: updatedContinuationToken, disallowContinuationTokenMessage: queryResponse.DisallowContinuationTokenMessage, activityId: queryResponse.ActivityId, requestCharge: queryResponse.RequestCharge, diagnostics: queryResponse.Diagnostics, responseLengthBytes: queryResponse.ResponseLengthBytes)); } catch (Exception) { this.component.Stop(); throw; } }
/// <summary> /// Gets the next page of results from this context. /// </summary> /// <param name="token">The cancellation token.</param> /// <returns>A task to await on that in turn returns a DoucmentFeedResponse of results.</returns> public override async Task <QueryResponseCore> ExecuteNextAsync(CancellationToken token) { try { QueryResponseCore queryResponse = await this.component.DrainAsync(this.actualPageSize, token); if (!queryResponse.IsSuccess) { this.component.Stop(); } return(queryResponse); } catch (Exception) { this.component.Stop(); throw; } }
internal static QueryResponseCore CreateFailure( HttpStatusCode statusCode, SubStatusCodes?subStatusCodes, string errorMessage, double requestCharge, string activityId, IReadOnlyCollection <QueryPageDiagnostics> diagnostics) { QueryResponseCore cosmosQueryResponse = new QueryResponseCore( result: QueryResponseCore.EmptyList, isSuccess: false, statusCode: statusCode, requestCharge: requestCharge, activityId: activityId, diagnostics: diagnostics, responseLengthBytes: 0, disallowContinuationTokenMessage: null, continuationToken: null, errorMessage: errorMessage, subStatusCode: subStatusCodes); return(cosmosQueryResponse); }
internal static QueryResponseCore CreateSuccess( IReadOnlyList <CosmosElement> result, double requestCharge, string activityId, long responseLengthBytes, string disallowContinuationTokenMessage, string continuationToken, IReadOnlyCollection <QueryPageDiagnostics> diagnostics) { QueryResponseCore cosmosQueryResponse = new QueryResponseCore( result: result, isSuccess: true, statusCode: HttpStatusCode.OK, requestCharge: requestCharge, activityId: activityId, diagnostics: diagnostics, responseLengthBytes: responseLengthBytes, disallowContinuationTokenMessage: disallowContinuationTokenMessage, continuationToken: continuationToken, errorMessage: null, subStatusCode: null); return(cosmosQueryResponse); }
public void RandomException() { QueryResponseCore queryResponse = QueryResponseFactory.CreateFromException(new Exception()); Assert.AreEqual(HttpStatusCode.InternalServerError, queryResponse.StatusCode); }
public override async Task <ResponseMessage> ReadNextAsync(CancellationToken cancellationToken = default(CancellationToken)) { // This catches exception thrown by the pipeline and converts it to QueryResponse ResponseMessage response; try { QueryResponseCore responseCore = await this.cosmosQueryExecutionContext.ExecuteNextAsync(cancellationToken); CosmosQueryContext cosmosQueryContext = this.cosmosQueryExecutionContext.CosmosQueryContext; QueryResponse queryResponse; if (responseCore.IsSuccess) { queryResponse = QueryResponse.CreateSuccess( result: responseCore.CosmosElements, count: responseCore.CosmosElements.Count, responseLengthBytes: responseCore.ResponseLengthBytes, queryMetrics: responseCore.QueryMetrics, responseHeaders: new CosmosQueryResponseMessageHeaders( responseCore.ContinuationToken, responseCore.DisallowContinuationTokenMessage, cosmosQueryContext.ResourceTypeEnum, cosmosQueryContext.ContainerResourceId) { RequestCharge = responseCore.RequestCharge, ActivityId = responseCore.ActivityId }); } else { queryResponse = QueryResponse.CreateFailure( statusCode: responseCore.StatusCode, error: null, errorMessage: responseCore.ErrorMessage, requestMessage: null, responseHeaders: new CosmosQueryResponseMessageHeaders( responseCore.ContinuationToken, responseCore.DisallowContinuationTokenMessage, cosmosQueryContext.ResourceTypeEnum, cosmosQueryContext.ContainerResourceId) { RequestCharge = responseCore.RequestCharge, ActivityId = responseCore.ActivityId }); } if (responseCore.QueryMetrics != null && responseCore.QueryMetrics.Count > 0) { queryResponse.Diagnostics = new QueryOperationStatistics(responseCore.QueryMetrics); } queryResponse.CosmosSerializationOptions = cosmosQueryContext.QueryRequestOptions.CosmosSerializationFormatOptions; response = queryResponse; } catch (Documents.DocumentClientException exception) { response = exception.ToCosmosResponseMessage(request: null); } catch (CosmosException exception) { response = exception.ToCosmosResponseMessage(request: null); } catch (AggregateException ae) { response = TransportHandler.AggregateExceptionConverter(ae, null); if (response == null) { throw; } } return(response); }
/// <summary> /// Given a document client exception this function determines whether it was caused due to a split. /// </summary> /// <param name="ex">The document client exception</param> /// <returns>Whether or not the exception was due to a split.</returns> private static bool IsSplitException(QueryResponseCore ex) { return(ex.StatusCode == HttpStatusCode.Gone && ex.SubStatusCode == Documents.SubStatusCodes.PartitionKeyRangeGone); }
public override async Task <QueryResponseCore> ExecuteNextAsync(CancellationToken cancellationToken) { if (this.responseMessageException != null) { return(this.responseMessageException.Value); } if (this.exception != null) { throw this.exception; } try { bool isFirstExecute = false; QueryResponseCore response; while (true) { // The retry policy handles the scenario when the name cache is stale. If the cache is stale the entire // execute context has incorrect values and should be recreated. This should only be done for the first // execution. If results have already been pulled an error should be returned to the user since it's // not possible to combine query results from multiple containers. if (this.innerExecutionContext == null) { TryCatch <CosmosQueryExecutionContext> tryCreateItemQueryExecutionContext = await this.TryCreateItemQueryExecutionContextAsync(cancellationToken); if (!tryCreateItemQueryExecutionContext.Succeeded) { // Failed to create pipeline (due to a bad request). return(QueryResponseCore.CreateFailure( HttpStatusCode.BadRequest, subStatusCodes: null, errorMessage: tryCreateItemQueryExecutionContext.Exception.ToString(), requestCharge: 0, activityId: this.CosmosQueryContext.CorrelatedActivityId.ToString(), diagnostics: QueryResponseCore.EmptyDiagnostics)); } this.innerExecutionContext = tryCreateItemQueryExecutionContext.Result; isFirstExecute = true; } response = await this.innerExecutionContext.ExecuteNextAsync(cancellationToken); if (response.IsSuccess) { break; } if (isFirstExecute && (response.StatusCode == HttpStatusCode.Gone) && (response.SubStatusCode == Documents.SubStatusCodes.NameCacheIsStale)) { await this.CosmosQueryContext.QueryClient.ForceRefreshCollectionCacheAsync( this.CosmosQueryContext.ResourceLink.OriginalString, cancellationToken); TryCatch <CosmosQueryExecutionContext> tryCreateItemQueryExecutionContext = await this.TryCreateItemQueryExecutionContextAsync(cancellationToken); if (!tryCreateItemQueryExecutionContext.Succeeded) { // Failed to create pipeline (due to a bad request). return(QueryResponseCore.CreateFailure( HttpStatusCode.BadRequest, subStatusCodes: null, errorMessage: tryCreateItemQueryExecutionContext.Exception.ToString(), requestCharge: 0, activityId: this.CosmosQueryContext.CorrelatedActivityId.ToString(), diagnostics: QueryResponseCore.EmptyDiagnostics)); } this.innerExecutionContext = tryCreateItemQueryExecutionContext.Result; isFirstExecute = false; } else { break; } } if (!response.IsSuccess) { this.responseMessageException = response; } return(response); } catch (Exception e) { this.exception = e; this.Dispose(); throw; } }