Exemple #1
0
        internal static async Task <TransactionalBatchResponse> FromResponseMessageAsync(
            ResponseMessage responseMessage,
            ServerBatchRequest serverRequest,
            CosmosSerializerCore serializer,
            bool shouldPromoteOperationStatus,
            ITrace trace,
            CancellationToken cancellationToken)
        {
            using (ITrace createResponseTrace = trace.StartChild("Create Trace", TraceComponent.Batch, TraceLevel.Info))
            {
                using (responseMessage)
                {
                    TransactionalBatchResponse response = null;
                    if (responseMessage.Content != null)
                    {
                        Stream content = responseMessage.Content;

                        // Shouldn't be the case practically, but handle it for safety.
                        if (!responseMessage.Content.CanSeek)
                        {
                            content = new MemoryStream();
                            await responseMessage.Content.CopyToAsync(content);
                        }

                        if (content.ReadByte() == (int)HybridRowVersion.V1)
                        {
                            content.Position = 0;
                            response         = await TransactionalBatchResponse.PopulateFromContentAsync(
                                content,
                                responseMessage,
                                serverRequest,
                                serializer,
                                trace,
                                shouldPromoteOperationStatus);

                            if (response == null)
                            {
                                // Convert any payload read failures as InternalServerError
                                response = new TransactionalBatchResponse(
                                    HttpStatusCode.InternalServerError,
                                    SubStatusCodes.Unknown,
                                    ClientResources.ServerResponseDeserializationFailure,
                                    responseMessage.Headers,
                                    trace,
                                    serverRequest.Operations,
                                    serializer);
                            }
                        }
                    }

                    if (response == null)
                    {
                        response = new TransactionalBatchResponse(
                            responseMessage.StatusCode,
                            responseMessage.Headers.SubStatusCode,
                            responseMessage.ErrorMessage,
                            responseMessage.Headers,
                            trace,
                            serverRequest.Operations,
                            serializer);
                    }

                    if (response.results == null || response.results.Count != serverRequest.Operations.Count)
                    {
                        if (responseMessage.IsSuccessStatusCode)
                        {
                            // Server should be guaranteeing number of results equal to operations when
                            // batch request is successful - so fail as InternalServerError if this is not the case.
                            response = new TransactionalBatchResponse(
                                HttpStatusCode.InternalServerError,
                                SubStatusCodes.Unknown,
                                ClientResources.InvalidServerResponse,
                                responseMessage.Headers,
                                trace,
                                serverRequest.Operations,
                                serializer);
                        }

                        // When the overall response status code is TooManyRequests, propagate the RetryAfter into the individual operations.
                        int retryAfterMilliseconds = 0;

                        if ((int)responseMessage.StatusCode == (int)StatusCodes.TooManyRequests)
                        {
                            if (!responseMessage.Headers.TryGetValue(HttpConstants.HttpHeaders.RetryAfterInMilliseconds, out string retryAfter) ||
                                retryAfter == null ||
                                !int.TryParse(retryAfter, out retryAfterMilliseconds))
                            {
                                retryAfterMilliseconds = 0;
                            }
                        }

                        response.CreateAndPopulateResults(serverRequest.Operations, trace, retryAfterMilliseconds);
                    }

                    return(response);
                }
            }
        }
Exemple #2
0
        internal static async Task <TransactionalBatchResponse> FromResponseMessageAsync(
            ResponseMessage responseMessage,
            ServerBatchRequest serverRequest,
            CosmosSerializerCore serializer,
            bool shouldPromoteOperationStatus,
            bool shouldPerformDecryption,
            CancellationToken cancellationToken)
        {
            using (responseMessage)
            {
                TransactionalBatchResponse response = null;
                if (responseMessage.Content != null)
                {
                    Stream content = responseMessage.Content;

                    // Shouldn't be the case practically, but handle it for safety.
                    if (!responseMessage.Content.CanSeek)
                    {
                        content = new MemoryStream();
                        await responseMessage.Content.CopyToAsync(content);
                    }

                    if (content.ReadByte() == (int)HybridRowVersion.V1)
                    {
                        content.Position = 0;
                        response         = await TransactionalBatchResponse.PopulateFromContentAsync(
                            content,
                            responseMessage,
                            serverRequest,
                            serializer,
                            shouldPromoteOperationStatus);

                        if (response == null)
                        {
                            // Convert any payload read failures as InternalServerError
                            response = new TransactionalBatchResponse(
                                HttpStatusCode.InternalServerError,
                                SubStatusCodes.Unknown,
                                ClientResources.ServerResponseDeserializationFailure,
                                responseMessage.Headers.RequestCharge,
                                responseMessage.Headers.RetryAfter,
                                responseMessage.Headers.ActivityId,
                                responseMessage.DiagnosticsContext,
                                serverRequest.Operations,
                                serializer);
                        }
                    }
                }

                if (response == null)
                {
                    response = new TransactionalBatchResponse(
                        responseMessage.StatusCode,
                        responseMessage.Headers.SubStatusCode,
                        responseMessage.ErrorMessage,
                        responseMessage.Headers.RequestCharge,
                        responseMessage.Headers.RetryAfter,
                        responseMessage.Headers.ActivityId,
                        responseMessage.DiagnosticsContext,
                        serverRequest.Operations,
                        serializer);
                }

                if (response.results == null || response.results.Count != serverRequest.Operations.Count)
                {
                    if (responseMessage.IsSuccessStatusCode)
                    {
                        // Server should be guaranteeing number of results equal to operations when
                        // batch request is successful - so fail as InternalServerError if this is not the case.
                        response = new TransactionalBatchResponse(
                            HttpStatusCode.InternalServerError,
                            SubStatusCodes.Unknown,
                            ClientResources.InvalidServerResponse,
                            responseMessage.Headers.RequestCharge,
                            responseMessage.Headers.RetryAfter,
                            responseMessage.Headers.ActivityId,
                            responseMessage.DiagnosticsContext,
                            serverRequest.Operations,
                            serializer);
                    }

                    // When the overall response status code is TooManyRequests, propagate the RetryAfter into the individual operations.
                    int retryAfterMilliseconds = 0;

                    if ((int)responseMessage.StatusCode == (int)StatusCodes.TooManyRequests)
                    {
                        if (!responseMessage.Headers.TryGetValue(HttpConstants.HttpHeaders.RetryAfterInMilliseconds, out string retryAfter) ||
                            retryAfter == null ||
                            !int.TryParse(retryAfter, out retryAfterMilliseconds))
                        {
                            retryAfterMilliseconds = 0;
                        }
                    }

                    response.CreateAndPopulateResults(serverRequest.Operations, retryAfterMilliseconds);
                }
                else if (shouldPerformDecryption)
                {
                    for (int index = 0; index < serverRequest.Operations.Count; index++)
                    {
                        ContainerCore containerCore = serverRequest.Operations[index].ContainerCore;
                        TransactionalBatchOperationResult result = response.results[index];
                        result.ResourceStream = await containerCore.ClientContext.DecryptItemAsync(
                            result.ResourceStream,
                            (DatabaseCore)containerCore.Database,
                            responseMessage.DiagnosticsContext,
                            cancellationToken);
                    }
                }

                return(response);
            }
        }