Beispiel #1
0
        private static QueryResponseCore GetCosmosElementResponse(
            Guid clientQueryCorrelationId,
            QueryRequestOptions requestOptions,
            ResourceType resourceType,
            ResponseMessage cosmosResponseMessage,
            PartitionKeyRangeIdentity partitionKeyRangeIdentity,
            Action <QueryPageDiagnostics> queryPageDiagnostics)
        {
            using (cosmosResponseMessage)
            {
                QueryPageDiagnostics queryPage = new QueryPageDiagnostics(
                    clientQueryCorrelationId: clientQueryCorrelationId,
                    partitionKeyRangeId: partitionKeyRangeIdentity.PartitionKeyRangeId,
                    queryMetricText: cosmosResponseMessage.Headers.QueryMetricsText,
                    indexUtilizationText: cosmosResponseMessage.Headers[HttpConstants.HttpHeaders.IndexUtilization],
                    diagnosticsContext: cosmosResponseMessage.DiagnosticsContext);
                queryPageDiagnostics(queryPage);

                if (!cosmosResponseMessage.IsSuccessStatusCode)
                {
                    return(QueryResponseCore.CreateFailure(
                               statusCode: cosmosResponseMessage.StatusCode,
                               subStatusCodes: cosmosResponseMessage.Headers.SubStatusCode,
                               cosmosException: cosmosResponseMessage.CosmosException,
                               requestCharge: cosmosResponseMessage.Headers.RequestCharge,
                               activityId: cosmosResponseMessage.Headers.ActivityId));
                }

                if (!(cosmosResponseMessage.Content is MemoryStream memoryStream))
                {
                    memoryStream = new MemoryStream();
                    cosmosResponseMessage.Content.CopyTo(memoryStream);
                }

                long        responseLengthBytes = memoryStream.Length;
                CosmosArray cosmosArray         = CosmosQueryClientCore.ParseElementsFromRestStream(
                    memoryStream,
                    resourceType,
                    requestOptions.CosmosSerializationFormatOptions);

                CosmosQueryExecutionInfo cosmosQueryExecutionInfo;
                if (cosmosResponseMessage.Headers.TryGetValue(QueryExecutionInfoHeader, out string queryExecutionInfoString))
                {
                    cosmosQueryExecutionInfo = JsonConvert.DeserializeObject <CosmosQueryExecutionInfo>(queryExecutionInfoString);
                }
                else
                {
                    cosmosQueryExecutionInfo = default;
                }

                return(QueryResponseCore.CreateSuccess(
                           result: cosmosArray,
                           requestCharge: cosmosResponseMessage.Headers.RequestCharge,
                           activityId: cosmosResponseMessage.Headers.ActivityId,
                           responseLengthBytes: responseLengthBytes,
                           disallowContinuationTokenMessage: null,
                           continuationToken: cosmosResponseMessage.Headers.ContinuationToken,
                           cosmosQueryExecutionInfo: cosmosQueryExecutionInfo));
            }
        }
        private static QueryResponseCore CreateFromExceptionWithStackTrace(ExceptionWithStackTraceException exceptionWithStackTrace)
        {
            // Use the original stack trace from the inner exception.
            if (exceptionWithStackTrace.InnerException is DocumentClientException ||
                exceptionWithStackTrace.InnerException is CosmosException)
            {
                return(QueryResponseFactory.CreateFromException(exceptionWithStackTrace.InnerException));
            }

            QueryResponseCore queryResponseCore = QueryResponseFactory.CreateFromException(exceptionWithStackTrace.InnerException);
            CosmosException   cosmosException   = queryResponseCore.CosmosException;

            queryResponseCore = QueryResponseCore.CreateFailure(
                statusCode: queryResponseCore.StatusCode,
                subStatusCodes: queryResponseCore.SubStatusCode,
                cosmosException: CosmosExceptionFactory.Create(
                    statusCode: cosmosException.StatusCode,
                    message: cosmosException.Message,
                    stackTrace: exceptionWithStackTrace.StackTrace,
                    headers: cosmosException.Headers,
                    trace: cosmosException.Trace,
                    error: cosmosException.Error,
                    innerException: cosmosException.InnerException),
                requestCharge: queryResponseCore.RequestCharge,
                activityId: queryResponseCore.ActivityId);

            return(queryResponseCore);
        }
        public static QueryResponseCore CreateFailureResponse(
            HttpStatusCode httpStatusCode,
            SubStatusCodes subStatusCodes,
            string errorMessage)
        {
            IReadOnlyCollection <QueryPageDiagnostics> diagnostics = new List <QueryPageDiagnostics>()
            {
                new QueryPageDiagnostics("0",
                                         "SomeQueryMetricText",
                                         "SomeIndexUtilText",
                                         new PointOperationStatistics(
                                             Guid.NewGuid().ToString(),
                                             System.Net.HttpStatusCode.Gone,
                                             subStatusCode: SubStatusCodes.PartitionKeyRangeGone,
                                             requestCharge: 10.4,
                                             errorMessage: null,
                                             method: HttpMethod.Post,
                                             requestUri: new Uri("http://localhost.com"),
                                             requestSessionToken: null,
                                             responseSessionToken: null,
                                             clientSideRequestStatistics: null),
                                         new SchedulingStopwatch())
            };

            QueryResponseCore splitResponse = QueryResponseCore.CreateFailure(
                statusCode: httpStatusCode,
                subStatusCodes: subStatusCodes,
                errorMessage: errorMessage,
                requestCharge: 10.4,
                activityId: Guid.NewGuid().ToString(),
                diagnostics: diagnostics);

            return(splitResponse);
        }
Beispiel #4
0
        private (Func <string, Task <IDocumentQueryExecutionComponent> >, QueryResponseCore) SetupBaseContextToVerifyFailureScenario()
        {
            IReadOnlyCollection <QueryPageDiagnostics> diagnostics = new List <QueryPageDiagnostics>()
            {
                new QueryPageDiagnostics("0",
                                         "SomeQueryMetricText",
                                         "SomeIndexUtilText",
                                         new PointOperationStatistics(
                                             Guid.NewGuid().ToString(),
                                             System.Net.HttpStatusCode.Unauthorized,
                                             subStatusCode: SubStatusCodes.PartitionKeyMismatch,
                                             requestCharge: 4,
                                             errorMessage: null,
                                             method: HttpMethod.Post,
                                             requestUri: new Uri("http://localhost.com"),
                                             clientSideRequestStatistics: null),
                                         new SchedulingStopwatch())
            };

            QueryResponseCore failure = QueryResponseCore.CreateFailure(
                System.Net.HttpStatusCode.Unauthorized,
                SubStatusCodes.PartitionKeyMismatch,
                "Random error message",
                42.89,
                "TestActivityId",
                diagnostics);

            Mock <IDocumentQueryExecutionComponent> baseContext = new Mock <IDocumentQueryExecutionComponent>();

            baseContext.Setup(x => x.DrainAsync(It.IsAny <int>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult <QueryResponseCore>(failure));
            Func <string, Task <IDocumentQueryExecutionComponent> > callBack = x => Task.FromResult <IDocumentQueryExecutionComponent>(baseContext.Object);

            return(callBack, failure);
        }
        private (Func <string, Task <TryCatch <IDocumentQueryExecutionComponent> > >, QueryResponseCore) SetupBaseContextToVerifyFailureScenario()
        {
            CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create();

            diagnosticsContext.AddDiagnosticsInternal(new PointOperationStatistics(
                                                          Guid.NewGuid().ToString(),
                                                          System.Net.HttpStatusCode.Unauthorized,
                                                          subStatusCode: SubStatusCodes.PartitionKeyMismatch,
                                                          requestCharge: 4,
                                                          errorMessage: null,
                                                          method: HttpMethod.Post,
                                                          requestUri: new Uri("http://localhost.com"),
                                                          requestSessionToken: null,
                                                          responseSessionToken: null,
                                                          clientSideRequestStatistics: null));
            IReadOnlyCollection <QueryPageDiagnostics> diagnostics = new List <QueryPageDiagnostics>()
            {
                new QueryPageDiagnostics(
                    "0",
                    "SomeQueryMetricText",
                    "SomeIndexUtilText",
                    diagnosticsContext,
                    new SchedulingStopwatch())
            };

            QueryResponseCore failure = QueryResponseCore.CreateFailure(
                System.Net.HttpStatusCode.Unauthorized,
                SubStatusCodes.PartitionKeyMismatch,
                new CosmosException(
                    statusCodes: HttpStatusCode.Unauthorized,
                    message: "Random error message",
                    subStatusCode: default,
Beispiel #6
0
        private QueryResponseCore GetCosmosElementResponse(
            QueryRequestOptions requestOptions,
            ResourceType resourceType,
            ResponseMessage cosmosResponseMessage,
            PartitionKeyRangeIdentity partitionKeyRangeIdentity,
            SchedulingStopwatch schedulingStopwatch)
        {
            using (cosmosResponseMessage)
            {
                QueryPageDiagnostics diagnostics = new QueryPageDiagnostics(
                    partitionKeyRangeId: partitionKeyRangeIdentity.PartitionKeyRangeId,
                    queryMetricText: cosmosResponseMessage.Headers.QueryMetricsText,
                    indexUtilizationText: cosmosResponseMessage.Headers[HttpConstants.HttpHeaders.IndexUtilization],
                    requestDiagnostics: cosmosResponseMessage.Diagnostics,
                    schedulingStopwatch: schedulingStopwatch);

                IReadOnlyCollection <QueryPageDiagnostics> pageDiagnostics = new List <QueryPageDiagnostics>()
                {
                    diagnostics
                };
                if (!cosmosResponseMessage.IsSuccessStatusCode)
                {
                    return(QueryResponseCore.CreateFailure(
                               statusCode: cosmosResponseMessage.StatusCode,
                               subStatusCodes: cosmosResponseMessage.Headers.SubStatusCode,
                               errorMessage: cosmosResponseMessage.ErrorMessage,
                               requestCharge: cosmosResponseMessage.Headers.RequestCharge,
                               activityId: cosmosResponseMessage.Headers.ActivityId,
                               diagnostics: pageDiagnostics));
                }

                MemoryStream memoryStream = cosmosResponseMessage.Content as MemoryStream;
                if (memoryStream == null)
                {
                    memoryStream = new MemoryStream();
                    cosmosResponseMessage.Content.CopyTo(memoryStream);
                }

                long        responseLengthBytes = memoryStream.Length;
                CosmosArray cosmosArray         = CosmosElementSerializer.ToCosmosElements(
                    memoryStream,
                    resourceType,
                    requestOptions.CosmosSerializationFormatOptions);

                int itemCount = cosmosArray.Count;
                return(QueryResponseCore.CreateSuccess(
                           result: cosmosArray,
                           requestCharge: cosmosResponseMessage.Headers.RequestCharge,
                           activityId: cosmosResponseMessage.Headers.ActivityId,
                           diagnostics: pageDiagnostics,
                           responseLengthBytes: cosmosResponseMessage.Headers.ContentLengthAsLong,
                           disallowContinuationTokenMessage: null,
                           continuationToken: cosmosResponseMessage.Headers.ContinuationToken));
            }
        }
        private static QueryResponseCore CreateFromCosmosException(CosmosException cosmosException)
        {
            QueryResponseCore queryResponseCore = QueryResponseCore.CreateFailure(
                statusCode: cosmosException.StatusCode,
                subStatusCodes: (Microsoft.Azure.Documents.SubStatusCodes)cosmosException.SubStatusCode,
                cosmosException: cosmosException,
                requestCharge: 0,
                activityId: cosmosException.ActivityId);

            return(queryResponseCore);
        }
Beispiel #8
0
        private static QueryResponseCore CreateFromCosmosException(CosmosException cosmosException)
        {
            QueryResponseCore queryResponseCore = QueryResponseCore.CreateFailure(
                statusCode: cosmosException.StatusCode,
                subStatusCodes: (Microsoft.Azure.Documents.SubStatusCodes)cosmosException.SubStatusCode,
                errorMessage: cosmosException.ToString(),
                requestCharge: 0,
                activityId: cosmosException.ActivityId,
                diagnostics: QueryResponseCore.EmptyDiagnostics);

            return(queryResponseCore);
        }
        public static QueryResponseCore CreateFromException(Exception exception)
        {
            QueryResponseCore queryResponseCore;

            if (exception is CosmosException cosmosException)
            {
                queryResponseCore = CreateFromCosmosException(cosmosException);
            }
            else if (exception is Microsoft.Azure.Documents.DocumentClientException documentClientException)
            {
                queryResponseCore = CreateFromDocumentClientException(documentClientException);
            }
            else if (exception is QueryException queryException)
            {
                CosmosException convertedException = queryException.Accept(QueryExceptionConverter.Singleton);
                queryResponseCore = CreateFromCosmosException(convertedException);
            }
            else if (exception is ExceptionWithStackTraceException exceptionWithStackTrace)
            {
                queryResponseCore = QueryResponseFactory.CreateFromExceptionWithStackTrace(exceptionWithStackTrace);
            }
            else
            {
                if (exception.InnerException != null)
                {
                    // retry with the inner exception
                    queryResponseCore = QueryResponseFactory.CreateFromException(exception.InnerException);
                }
                else
                {
                    CosmosException unkownCosmosException = CosmosExceptionFactory.CreateInternalServerErrorException(
                        headers: new Headers()
                    {
                        SubStatusCode = SubStatusCodes.PartitionKeyRangeGone,
                        ActivityId    = QueryResponseCore.EmptyGuidString
                    },
                        message: exception.Message,
                        stackTrace: exception.StackTrace,
                        trace: NoOpTrace.Singleton,
                        innerException: exception);

                    // Unknown exception type should become a 500
                    queryResponseCore = QueryResponseCore.CreateFailure(
                        statusCode: System.Net.HttpStatusCode.InternalServerError,
                        subStatusCodes: null,
                        cosmosException: unkownCosmosException,
                        requestCharge: 0,
                        activityId: QueryResponseCore.EmptyGuidString);
                }
            }

            return(queryResponseCore);
        }
Beispiel #10
0
        private static QueryResponseCore CreateFromDocumentClientException(Microsoft.Azure.Documents.DocumentClientException documentClientException)
        {
            QueryResponseCore queryResponseCore = QueryResponseCore.CreateFailure(
                statusCode: documentClientException.StatusCode.GetValueOrDefault(System.Net.HttpStatusCode.InternalServerError),
                subStatusCodes: null,
                errorMessage: documentClientException.ToString(),
                requestCharge: 0,
                activityId: documentClientException.ActivityId,
                diagnostics: QueryResponseCore.EmptyDiagnostics);

            return(queryResponseCore);
        }
        public static QueryResponseCore CreateSplitResponse(string collectionRid)
        {
            QueryResponseCore splitResponse = QueryResponseCore.CreateFailure(
                statusCode: HttpStatusCode.Gone,
                subStatusCodes: SubStatusCodes.PartitionKeyRangeGone,
                errorMessage: "Partition split error",
                requestCharge: 10.4,
                activityId: Guid.NewGuid().ToString(),
                queryMetricsText: null,
                queryMetrics: null);

            return(splitResponse);
        }
        private QueryResponseCore GetCosmosElementResponse(
            Guid clientQueryCorrelationId,
            QueryRequestOptions requestOptions,
            ResourceType resourceType,
            ResponseMessage cosmosResponseMessage,
            PartitionKeyRangeIdentity partitionKeyRangeIdentity,
            Action <QueryPageDiagnostics> queryPageDiagnostics)
        {
            using (cosmosResponseMessage)
            {
                QueryPageDiagnostics queryPage = new QueryPageDiagnostics(
                    clientQueryCorrelationId: clientQueryCorrelationId,
                    partitionKeyRangeId: partitionKeyRangeIdentity.PartitionKeyRangeId,
                    queryMetricText: cosmosResponseMessage.Headers.QueryMetricsText,
                    indexUtilizationText: cosmosResponseMessage.Headers[HttpConstants.HttpHeaders.IndexUtilization],
                    diagnosticsContext: cosmosResponseMessage.DiagnosticsContext);
                queryPageDiagnostics(queryPage);

                if (!cosmosResponseMessage.IsSuccessStatusCode)
                {
                    return(QueryResponseCore.CreateFailure(
                               statusCode: cosmosResponseMessage.StatusCode,
                               subStatusCodes: cosmosResponseMessage.Headers.SubStatusCode,
                               cosmosException: cosmosResponseMessage.CosmosException,
                               requestCharge: cosmosResponseMessage.Headers.RequestCharge,
                               activityId: cosmosResponseMessage.Headers.ActivityId));
                }

                if (!(cosmosResponseMessage.Content is MemoryStream memoryStream))
                {
                    memoryStream = new MemoryStream();
                    cosmosResponseMessage.Content.CopyTo(memoryStream);
                }

                long        responseLengthBytes = memoryStream.Length;
                CosmosArray cosmosArray         = CosmosElementSerializer.ToCosmosElements(
                    memoryStream,
                    resourceType,
                    requestOptions.CosmosSerializationFormatOptions);

                int itemCount = cosmosArray.Count;
                return(QueryResponseCore.CreateSuccess(
                           result: cosmosArray,
                           requestCharge: cosmosResponseMessage.Headers.RequestCharge,
                           activityId: cosmosResponseMessage.Headers.ActivityId,
                           responseLengthBytes: responseLengthBytes,
                           disallowContinuationTokenMessage: null,
                           continuationToken: cosmosResponseMessage.Headers.ContinuationToken));
            }
        }
Beispiel #13
0
        public static QueryResponseCore CreateFromException(Exception exception)
        {
            QueryResponseCore queryResponseCore;

            if (exception is CosmosException cosmosException)
            {
                queryResponseCore = CreateFromCosmosException(cosmosException);
            }
            else if (exception is Microsoft.Azure.Documents.DocumentClientException documentClientException)
            {
                queryResponseCore = CreateFromDocumentClientException(documentClientException);
            }
            else if (exception is QueryException queryException)
            {
                CosmosException convertedException = queryException.Accept(QueryExceptionConverter.Singleton);
                queryResponseCore = CreateFromCosmosException(convertedException);
            }
            else if (exception is ExceptionWithStackTraceException exceptionWithStackTrace)
            {
                QueryResponseCore innerExceptionResponse = QueryResponseFactory.CreateFromException(exceptionWithStackTrace.InnerException);
                queryResponseCore = QueryResponseCore.CreateFailure(
                    statusCode: innerExceptionResponse.StatusCode,
                    subStatusCodes: innerExceptionResponse.SubStatusCode,
                    errorMessage: exceptionWithStackTrace.ToString(),
                    requestCharge: innerExceptionResponse.RequestCharge,
                    activityId: innerExceptionResponse.ActivityId,
                    diagnostics: innerExceptionResponse.Diagnostics);
            }
            else
            {
                if (exception.InnerException != null)
                {
                    // retry with the inner exception
                    queryResponseCore = QueryResponseFactory.CreateFromException(exception.InnerException);
                }
                else
                {
                    // Unknown exception type should become a 500
                    queryResponseCore = QueryResponseCore.CreateFailure(
                        statusCode: System.Net.HttpStatusCode.InternalServerError,
                        subStatusCodes: null,
                        errorMessage: exception?.ToString(),
                        requestCharge: 0,
                        activityId: QueryResponseCore.EmptyGuidString,
                        diagnostics: QueryResponseCore.EmptyDiagnostics);
                }
            }

            return(queryResponseCore);
        }
        private static QueryResponseCore CreateFromDocumentClientException(Microsoft.Azure.Documents.DocumentClientException documentClientException)
        {
            CosmosException cosmosException = CosmosExceptionFactory.Create(
                documentClientException,
                null);

            QueryResponseCore queryResponseCore = QueryResponseCore.CreateFailure(
                statusCode: documentClientException.StatusCode.GetValueOrDefault(System.Net.HttpStatusCode.InternalServerError),
                subStatusCodes: null,
                cosmosException: cosmosException,
                requestCharge: 0,
                activityId: documentClientException.ActivityId);

            return(queryResponseCore);
        }
Beispiel #15
0
        public static QueryResponseCore CreateFailureResponse(
            HttpStatusCode httpStatusCode,
            SubStatusCodes subStatusCodes,
            string errorMessage)
        {
            QueryResponseCore splitResponse = QueryResponseCore.CreateFailure(
                statusCode: httpStatusCode,
                subStatusCodes: subStatusCodes,
                errorMessage: errorMessage,
                requestCharge: 10.4,
                activityId: Guid.NewGuid().ToString(),
                queryMetricsText: null,
                queryMetrics: null);

            return(splitResponse);
        }
        private QueryResponseCore GetCosmosElementResponse(
            QueryRequestOptions requestOptions,
            ResourceType resourceType,
            ResponseMessage cosmosResponseMessage)
        {
            using (cosmosResponseMessage)
            {
                if (!cosmosResponseMessage.IsSuccessStatusCode)
                {
                    return(QueryResponseCore.CreateFailure(
                               statusCode: cosmosResponseMessage.StatusCode,
                               subStatusCodes: cosmosResponseMessage.Headers.SubStatusCode,
                               errorMessage: cosmosResponseMessage.ErrorMessage,
                               requestCharge: cosmosResponseMessage.Headers.RequestCharge,
                               activityId: cosmosResponseMessage.Headers.ActivityId,
                               queryMetricsText: cosmosResponseMessage.Headers.QueryMetricsText,
                               queryMetrics: null));
                }

                MemoryStream memoryStream = cosmosResponseMessage.Content as MemoryStream;
                if (memoryStream == null)
                {
                    memoryStream = new MemoryStream();
                    cosmosResponseMessage.Content.CopyTo(memoryStream);
                }

                long        responseLengthBytes = memoryStream.Length;
                CosmosArray cosmosArray         = CosmosElementSerializer.ToCosmosElements(
                    memoryStream,
                    resourceType,
                    requestOptions.CosmosSerializationFormatOptions);

                int itemCount = cosmosArray.Count;
                return(QueryResponseCore.CreateSuccess(
                           result: cosmosArray,
                           requestCharge: cosmosResponseMessage.Headers.RequestCharge,
                           activityId: cosmosResponseMessage.Headers.ActivityId,
                           queryMetricsText: cosmosResponseMessage.Headers.QueryMetricsText,
                           queryMetrics: null,
                           requestStatistics: null,
                           responseLengthBytes: cosmosResponseMessage.Headers.ContentLengthAsLong,
                           disallowContinuationTokenMessage: null,
                           continuationToken: cosmosResponseMessage.Headers.ContinuationToken));
            }
        }
        private (Func <string, Task <IDocumentQueryExecutionComponent> >, QueryResponseCore) SetupBaseContextToVerifyFailureScenario()
        {
            QueryResponseCore failure = QueryResponseCore.CreateFailure(
                System.Net.HttpStatusCode.Unauthorized,
                SubStatusCodes.PartitionKeyMismatch,
                "Random error message",
                42.89,
                "TestActivityId",
                null,
                null);

            Mock <IDocumentQueryExecutionComponent> baseContext = new Mock <IDocumentQueryExecutionComponent>();

            baseContext.Setup(x => x.DrainAsync(It.IsAny <int>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult <QueryResponseCore>(failure));
            Func <string, Task <IDocumentQueryExecutionComponent> > callBack = x => Task.FromResult <IDocumentQueryExecutionComponent>(baseContext.Object);

            return(callBack, failure);
        }
        public static QueryResponseCore CreateFromException(Exception exception)
        {
            // Get the inner most exception
            while (exception.InnerException != null)
            {
                exception = exception.InnerException;
            }

            QueryResponseCore queryResponseCore;

            if (exception is CosmosException cosmosException)
            {
                queryResponseCore = CreateFromCosmosException(cosmosException);
            }
            else if (exception is Microsoft.Azure.Documents.DocumentClientException documentClientException)
            {
                queryResponseCore = CreateFromDocumentClientException(documentClientException);
            }
            else if (exception is QueryException queryException)
            {
                CosmosException convertedException = queryException.Accept(QueryExceptionConverter.Singleton);
                queryResponseCore = CreateFromCosmosException(convertedException);
            }
            else
            {
                // Unknown exception type should become a 500
                queryResponseCore = QueryResponseCore.CreateFailure(
                    statusCode: System.Net.HttpStatusCode.InternalServerError,
                    subStatusCodes: null,
                    errorMessage: exception.ToString(),
                    requestCharge: 0,
                    activityId: QueryResponseCore.EmptyGuidString,
                    diagnostics: QueryResponseCore.EmptyDiagnostics);
            }

            return(queryResponseCore);
        }
        public async Task TestItemProducerTreeWithFailure()
        {
            int callBackCount = 0;
            Mock <CosmosQueryContext> mockQueryContext = new Mock <CosmosQueryContext>();

            SqlQuerySpec      sqlQuerySpec      = new SqlQuerySpec("Select * from t");
            PartitionKeyRange partitionKeyRange = new PartitionKeyRange {
                Id = "0", MinInclusive = "A", MaxExclusive = "B"
            };

            void produceAsyncCompleteCallback(
                ItemProducerTree producer,
                int itemsBuffered,
                double resourceUnitUsage,
                IReadOnlyCollection <QueryPageDiagnostics> queryPageDiagnostics,
                long responseLengthBytes,
                CancellationToken token)
            {
                callBackCount++;
            }

            Mock <IComparer <ItemProducerTree> >      comparer = new Mock <IComparer <ItemProducerTree> >();
            Mock <IEqualityComparer <CosmosElement> > cosmosElementComparer = new Mock <IEqualityComparer <CosmosElement> >();
            CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();

            IReadOnlyList <CosmosElement> cosmosElements = new List <CosmosElement>()
            {
                new Mock <CosmosElement>(CosmosElementType.Object).Object
            };

            QueryPageDiagnostics diagnostics = new QueryPageDiagnostics(
                partitionKeyRangeId: "0",
                queryMetricText: "SomeRandomQueryMetricText",
                indexUtilizationText: null,
                requestDiagnostics: new PointOperationStatistics(
                    Guid.NewGuid().ToString(),
                    System.Net.HttpStatusCode.OK,
                    subStatusCode: SubStatusCodes.Unknown,
                    requestCharge: 42,
                    errorMessage: null,
                    method: HttpMethod.Post,
                    requestUri: new Uri("http://localhost.com"),
                    requestSessionToken: null,
                    responseSessionToken: null,
                    clientSideRequestStatistics: null),
                schedulingStopwatch: new SchedulingStopwatch());
            IReadOnlyCollection <QueryPageDiagnostics> pageDiagnostics = new List <QueryPageDiagnostics>()
            {
                diagnostics
            };

            mockQueryContext.Setup(x => x.ContainerResourceId).Returns("MockCollectionRid");
            mockQueryContext.Setup(x => x.ExecuteQueryAsync(
                                       sqlQuerySpec,
                                       It.IsAny <string>(),
                                       It.IsAny <PartitionKeyRangeIdentity>(),
                                       It.IsAny <bool>(),
                                       It.IsAny <int>(),
                                       It.IsAny <SchedulingStopwatch>(),
                                       cancellationTokenSource.Token)).Returns(
                Task.FromResult(QueryResponseCore.CreateSuccess(
                                    result: cosmosElements,
                                    requestCharge: 42,
                                    activityId: "AA470D71-6DEF-4D61-9A08-272D8C9ABCFE",
                                    diagnostics: pageDiagnostics,
                                    responseLengthBytes: 500,
                                    disallowContinuationTokenMessage: null,
                                    continuationToken: "TestToken")));

            ItemProducerTree itemProducerTree = new ItemProducerTree(
                queryContext: mockQueryContext.Object,
                querySpecForInit: sqlQuerySpec,
                partitionKeyRange: partitionKeyRange,
                produceAsyncCompleteCallback: produceAsyncCompleteCallback,
                itemProducerTreeComparer: comparer.Object,
                equalityComparer: cosmosElementComparer.Object,
                testSettings: new TestInjections(simulate429s: false, simulateEmptyPages: false),
                deferFirstPage: false,
                collectionRid: "collectionRid",
                initialContinuationToken: null,
                initialPageSize: 50);

            // Buffer to success responses
            await itemProducerTree.BufferMoreDocumentsAsync(cancellationTokenSource.Token);

            await itemProducerTree.BufferMoreDocumentsAsync(cancellationTokenSource.Token);

            diagnostics = new QueryPageDiagnostics(
                partitionKeyRangeId: "0",
                queryMetricText: null,
                indexUtilizationText: null,
                requestDiagnostics: new PointOperationStatistics(
                    Guid.NewGuid().ToString(),
                    System.Net.HttpStatusCode.InternalServerError,
                    subStatusCode: SubStatusCodes.Unknown,
                    requestCharge: 10.2,
                    errorMessage: "Error message",
                    method: HttpMethod.Post,
                    requestUri: new Uri("http://localhost.com"),
                    requestSessionToken: null,
                    responseSessionToken: null,
                    clientSideRequestStatistics: null),
                schedulingStopwatch: new SchedulingStopwatch());
            pageDiagnostics = new List <QueryPageDiagnostics>()
            {
                diagnostics
            };

            // Buffer a failure
            mockQueryContext.Setup(x => x.ExecuteQueryAsync(
                                       sqlQuerySpec,
                                       It.IsAny <string>(),
                                       It.IsAny <PartitionKeyRangeIdentity>(),
                                       It.IsAny <bool>(),
                                       It.IsAny <int>(),
                                       It.IsAny <SchedulingStopwatch>(),
                                       cancellationTokenSource.Token)).Returns(
                Task.FromResult(QueryResponseCore.CreateFailure(
                                    statusCode: HttpStatusCode.InternalServerError,
                                    subStatusCodes: null,
                                    errorMessage: "Error message",
                                    requestCharge: 10.2,
                                    activityId: Guid.NewGuid().ToString(),
                                    diagnostics: pageDiagnostics)));

            await itemProducerTree.BufferMoreDocumentsAsync(cancellationTokenSource.Token);

            // First item should be a success
            {
                (bool movedToNextPage, QueryResponseCore? failureResponse) = await itemProducerTree.TryMoveNextPageAsync(cancellationTokenSource.Token);

                Assert.IsTrue(movedToNextPage);
                Assert.IsNull(failureResponse);
                Assert.IsTrue(itemProducerTree.TryMoveNextDocumentWithinPage());
                Assert.IsFalse(itemProducerTree.TryMoveNextDocumentWithinPage());
                Assert.IsTrue(itemProducerTree.HasMoreResults);
            }

            // Second item should be a success
            {
                (bool movedToNextPage, QueryResponseCore? failureResponse) = await itemProducerTree.TryMoveNextPageAsync(cancellationTokenSource.Token);

                Assert.IsTrue(movedToNextPage);
                Assert.IsNull(failureResponse);
                Assert.IsTrue(itemProducerTree.TryMoveNextDocumentWithinPage());
                Assert.IsFalse(itemProducerTree.TryMoveNextDocumentWithinPage());
                Assert.IsTrue(itemProducerTree.HasMoreResults);
            }

            // Third item should be a failure
            {
                (bool movedToNextPage, QueryResponseCore? failureResponse) = await itemProducerTree.TryMoveNextPageAsync(cancellationTokenSource.Token);

                Assert.IsFalse(movedToNextPage);
                Assert.IsNotNull(failureResponse);
                Assert.IsFalse(itemProducerTree.HasMoreResults);
            }

            // Try to buffer after failure. It should return the previous cached failure and not try to buffer again.
            mockQueryContext.Setup(x => x.ExecuteQueryAsync(
                                       sqlQuerySpec,
                                       It.IsAny <string>(),
                                       It.IsAny <PartitionKeyRangeIdentity>(),
                                       It.IsAny <bool>(),
                                       It.IsAny <int>(),
                                       It.IsAny <SchedulingStopwatch>(),
                                       cancellationTokenSource.Token)).
            Throws(new Exception("Previous buffer failed. Operation should return original failure and not try again"));

            await itemProducerTree.BufferMoreDocumentsAsync(cancellationTokenSource.Token);

            Assert.IsFalse(itemProducerTree.HasMoreResults);
        }
        public async Task TestItemProducerTreeWithFailure()
        {
            int callBackCount = 0;
            Mock <CosmosQueryContext> mockQueryContext = new Mock <CosmosQueryContext>();

            SqlQuerySpec      sqlQuerySpec      = new SqlQuerySpec("Select * from t");
            PartitionKeyRange partitionKeyRange = new PartitionKeyRange {
                Id = "0", MinInclusive = "A", MaxExclusive = "B"
            };

            ItemProducerTree.ProduceAsyncCompleteDelegate produceAsyncCompleteCallback = (
                ItemProducerTree producer,
                int itemsBuffered,
                double resourceUnitUsage,
                QueryMetrics queryMetrics,
                long responseLengthBytes,
                CancellationToken token) =>
            { callBackCount++; };

            Mock <IComparer <ItemProducerTree> >      comparer = new Mock <IComparer <ItemProducerTree> >();
            Mock <IEqualityComparer <CosmosElement> > cosmosElementComparer = new Mock <IEqualityComparer <CosmosElement> >();
            CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();

            IReadOnlyList <CosmosElement> cosmosElements = new List <CosmosElement>()
            {
                new Mock <CosmosElement>(CosmosElementType.Object).Object
            };

            mockQueryContext.Setup(x => x.ContainerResourceId).Returns("MockCollectionRid");
            mockQueryContext.Setup(x => x.ExecuteQueryAsync(
                                       sqlQuerySpec,
                                       It.IsAny <string>(),
                                       It.IsAny <PartitionKeyRangeIdentity>(),
                                       It.IsAny <bool>(),
                                       It.IsAny <int>(),
                                       cancellationTokenSource.Token)).Returns(
                Task.FromResult(QueryResponseCore.CreateSuccess(
                                    result: cosmosElements,
                                    requestCharge: 42,
                                    activityId: "AA470D71-6DEF-4D61-9A08-272D8C9ABCFE",
                                    queryMetrics: null,
                                    queryMetricsText: null,
                                    requestStatistics: null,
                                    responseLengthBytes: 500,
                                    disallowContinuationTokenMessage: null,
                                    continuationToken: "TestToken")));

            ItemProducerTree itemProducerTree = new ItemProducerTree(
                queryContext: mockQueryContext.Object,
                querySpecForInit: sqlQuerySpec,
                partitionKeyRange: partitionKeyRange,
                produceAsyncCompleteCallback: produceAsyncCompleteCallback,
                itemProducerTreeComparer: comparer.Object,
                equalityComparer: cosmosElementComparer.Object,
                deferFirstPage: false,
                collectionRid: "collectionRid",
                initialContinuationToken: null,
                initialPageSize: 50);

            // Buffer to success responses
            await itemProducerTree.BufferMoreDocumentsAsync(cancellationTokenSource.Token);

            await itemProducerTree.BufferMoreDocumentsAsync(cancellationTokenSource.Token);

            // Buffer a failure
            mockQueryContext.Setup(x => x.ExecuteQueryAsync(
                                       sqlQuerySpec,
                                       It.IsAny <string>(),
                                       It.IsAny <PartitionKeyRangeIdentity>(),
                                       It.IsAny <bool>(),
                                       It.IsAny <int>(),
                                       cancellationTokenSource.Token)).Returns(
                Task.FromResult(QueryResponseCore.CreateFailure(
                                    statusCode: HttpStatusCode.InternalServerError,
                                    subStatusCodes: null,
                                    errorMessage: "Error message",
                                    requestCharge: 10.2,
                                    activityId: Guid.NewGuid().ToString(),
                                    queryMetricsText: null,
                                    queryMetrics: null)));

            await itemProducerTree.BufferMoreDocumentsAsync(cancellationTokenSource.Token);

            // First item should be a success
            (bool successfullyMovedNext, QueryResponseCore? failureResponse)result = await itemProducerTree.MoveNextAsync(cancellationTokenSource.Token);

            Assert.IsTrue(result.successfullyMovedNext);
            Assert.IsNull(result.failureResponse);
            Assert.IsTrue(itemProducerTree.HasMoreResults);

            // Second item should be a success
            result = await itemProducerTree.MoveNextAsync(cancellationTokenSource.Token);

            Assert.IsTrue(result.successfullyMovedNext);
            Assert.IsNull(result.failureResponse);
            Assert.IsTrue(itemProducerTree.HasMoreResults);

            // Third item should be a failure
            result = await itemProducerTree.MoveNextAsync(cancellationTokenSource.Token);

            Assert.IsFalse(result.successfullyMovedNext);
            Assert.IsNotNull(result.failureResponse);
            Assert.IsFalse(itemProducerTree.HasMoreResults);

            // Try to buffer after failure. It should return the previous cached failure and not try to buffer again.
            mockQueryContext.Setup(x => x.ExecuteQueryAsync(
                                       sqlQuerySpec,
                                       It.IsAny <string>(),
                                       It.IsAny <PartitionKeyRangeIdentity>(),
                                       It.IsAny <bool>(),
                                       It.IsAny <int>(),
                                       cancellationTokenSource.Token)).
            Throws(new Exception("Previous buffer failed. Operation should return original failure and not try again"));

            await itemProducerTree.BufferMoreDocumentsAsync(cancellationTokenSource.Token);

            Assert.IsFalse(result.successfullyMovedNext);
            Assert.IsNotNull(result.failureResponse);
            Assert.IsFalse(itemProducerTree.HasMoreResults);
        }