internal async Task <ResponseMessage> ProcessItemStreamAsync( PartitionKey?partitionKey, string itemId, Stream streamPayload, OperationType operationType, ItemRequestOptions requestOptions, CosmosDiagnosticsContext diagnosticsContext, CancellationToken cancellationToken) { if (requestOptions != null && requestOptions.IsEffectivePartitionKeyRouting) { partitionKey = null; } ContainerCore.ValidatePartitionKey(partitionKey, requestOptions); Uri resourceUri = this.GetResourceUri(requestOptions, operationType, itemId); if (diagnosticsContext == null) { diagnosticsContext = CosmosDiagnosticsContext.Create(requestOptions); } using (diagnosticsContext.CreateOverallScope("ProcessItemStream")) { if (requestOptions != null && requestOptions.EncryptionOptions != null) { if (streamPayload == null) { throw new ArgumentException(ClientResources.InvalidRequestWithEncryptionOptions); } using (diagnosticsContext.CreateScope("Encrypt")) { streamPayload = await this.ClientContext.EncryptionProcessor.EncryptAsync( streamPayload, requestOptions.EncryptionOptions, (DatabaseCore)this.Database, this.ClientContext.ClientOptions.EncryptionKeyWrapProvider, diagnosticsContext, cancellationToken); } } ResponseMessage responseMessage = await this.ClientContext.ProcessResourceOperationStreamAsync( resourceUri : resourceUri, resourceType : ResourceType.Document, operationType : operationType, requestOptions : requestOptions, cosmosContainerCore : this, partitionKey : partitionKey, itemId : itemId, streamPayload : streamPayload, requestEnricher : null, diagnosticsScope : diagnosticsContext, cancellationToken : cancellationToken); if (responseMessage.Content != null && this.ClientContext.ClientOptions.EncryptionKeyWrapProvider != null) { using (diagnosticsContext.CreateScope("Decrypt")) { responseMessage.Content = await this.ClientContext.EncryptionProcessor.DecryptAsync( responseMessage.Content, (DatabaseCore)this.Database, this.ClientContext.ClientOptions.EncryptionKeyWrapProvider, diagnosticsContext, cancellationToken); } } return(responseMessage); } }
public virtual Task <bool> ShouldRetryAsync( ContainerCore containerCore, ResponseMessage responseMessage, CancellationToken cancellationToken = default(CancellationToken)) => Task.FromResult(false);
private static TryCatch <QueryPage> GetCosmosElementResponse( QueryRequestOptions requestOptions, ResourceType resourceType, ResponseMessage cosmosResponseMessage, ITrace trace) { using (ITrace getCosmosElementResponse = trace.StartChild("Get Cosmos Element Response", TraceComponent.Json, Tracing.TraceLevel.Info)) { using (cosmosResponseMessage) { if (cosmosResponseMessage.Headers.QueryMetricsText != null) { QueryMetricsTraceDatum datum = new QueryMetricsTraceDatum( new Lazy <QueryMetrics>(() => new QueryMetrics( cosmosResponseMessage.Headers.QueryMetricsText, IndexUtilizationInfo.Empty, ClientSideMetrics.Empty))); trace.AddDatum("Query Metrics", datum); } if (!cosmosResponseMessage.IsSuccessStatusCode) { CosmosException exception = cosmosResponseMessage.CosmosException ?? new CosmosException( cosmosResponseMessage.ErrorMessage, cosmosResponseMessage.StatusCode, (int)cosmosResponseMessage.Headers.SubStatusCode, cosmosResponseMessage.Headers.ActivityId, cosmosResponseMessage.Headers.RequestCharge); return(TryCatch <QueryPage> .FromException(exception)); } if (!(cosmosResponseMessage.Content is MemoryStream memoryStream)) { memoryStream = new MemoryStream(); cosmosResponseMessage.Content.CopyTo(memoryStream); } long responseLengthBytes = memoryStream.Length; CosmosArray documents = CosmosQueryClientCore.ParseElementsFromRestStream( memoryStream, resourceType, requestOptions.CosmosSerializationFormatOptions); QueryState queryState; if (cosmosResponseMessage.Headers.ContinuationToken != null) { queryState = new QueryState(CosmosString.Create(cosmosResponseMessage.Headers.ContinuationToken)); } else { queryState = default; } Dictionary <string, string> additionalHeaders = new Dictionary <string, string>(); foreach (string key in cosmosResponseMessage.Headers) { if (!QueryPage.BannedHeaders.Contains(key)) { additionalHeaders[key] = cosmosResponseMessage.Headers[key]; } } Lazy <CosmosQueryExecutionInfo> cosmosQueryExecutionInfo = default; if (cosmosResponseMessage.Headers.TryGetValue(QueryExecutionInfoHeader, out string queryExecutionInfoString)) { cosmosQueryExecutionInfo = new Lazy <CosmosQueryExecutionInfo>( () => JsonConvert.DeserializeObject <CosmosQueryExecutionInfo>(queryExecutionInfoString)); } QueryPage response = new QueryPage( documents, cosmosResponseMessage.Headers.RequestCharge, cosmosResponseMessage.Headers.ActivityId, responseLengthBytes, cosmosQueryExecutionInfo, disallowContinuationTokenMessage: null, additionalHeaders, queryState); return(TryCatch <QueryPage> .FromResult(response)); } } }
public Task <ShouldRetryResult> ShouldRetryAsync( ResponseMessage cosmosResponseMessage, CancellationToken cancellationToken) { throw new NotImplementedException(); }
public override async Task <ContainerResponse> CreateContainerIfNotExistsAsync( ContainerProperties containerProperties, int?throughput = null, RequestOptions requestOptions = null, CancellationToken cancellationToken = default(CancellationToken)) { if (containerProperties == null) { throw new ArgumentNullException(nameof(containerProperties)); } this.ValidateContainerProperties(containerProperties); Container container = this.GetContainer(containerProperties.Id); ResponseMessage readResponse = await container.ReadContainerStreamAsync( cancellationToken : cancellationToken); if (readResponse.StatusCode != HttpStatusCode.NotFound) { ContainerResponse retrivedContainerResponse = await this.ClientContext.ResponseFactory.CreateContainerResponseAsync( container, Task.FromResult(readResponse)); if (!retrivedContainerResponse.Resource.PartitionKeyPath.Equals(containerProperties.PartitionKeyPath)) { throw new ArgumentException( string.Format( ClientResources.PartitionKeyPathConflict, containerProperties.PartitionKeyPath, containerProperties.Id, retrivedContainerResponse.Resource.PartitionKeyPath), nameof(containerProperties.PartitionKey)); } return(retrivedContainerResponse); } this.ValidateContainerProperties(containerProperties); ResponseMessage createResponse = await this.CreateContainerStreamAsync( containerProperties, throughput, requestOptions, cancellationToken); // Merge the previous message diagnostics createResponse.DiagnosticsContext.AddDiagnosticsInternal(readResponse.DiagnosticsContext); if (readResponse.StatusCode != HttpStatusCode.Conflict) { return(await this.ClientContext.ResponseFactory.CreateContainerResponseAsync(container, Task.FromResult(createResponse))); } // This second Read is to handle the race condition when 2 or more threads have Read the database and only one succeeds with Create // so for the remaining ones we should do a Read instead of throwing Conflict exception ResponseMessage readResponseAfterCreate = await container.ReadContainerStreamAsync( cancellationToken : cancellationToken); // Merge the previous message diagnostics createResponse.DiagnosticsContext.AddDiagnosticsInternal(readResponse.DiagnosticsContext); return(await this.ClientContext.ResponseFactory.CreateContainerResponseAsync(container, Task.FromResult(readResponseAfterCreate))); }
internal static string GetContinuationToken(ResponseMessage httpResponseMessage) { return(httpResponseMessage.Headers.Continuation); }
public override StoredProcedureExecuteResponse <T> CreateStoredProcedureExecuteResponse <T>(ResponseMessage responseMessage) { return(this.ProcessMessage(responseMessage, (cosmosResponseMessage) => { T item = this.ToObjectpublic <T>(cosmosResponseMessage); return new StoredProcedureExecuteResponse <T>( cosmosResponseMessage.StatusCode, cosmosResponseMessage.Headers, item, cosmosResponseMessage.Diagnostics); })); }
public async Task <ContainerResponse> CreateContainerIfNotExistsAsync( CosmosDiagnosticsContext diagnosticsContext, ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions, CancellationToken cancellationToken) { if (containerProperties == null) { throw new ArgumentNullException(nameof(containerProperties)); } this.ValidateContainerProperties(containerProperties); ContainerCore container = (ContainerCore)this.GetContainer(containerProperties.Id); using (ResponseMessage readResponse = await container.ReadContainerStreamAsync( diagnosticsContext: diagnosticsContext, cancellationToken: cancellationToken)) { if (readResponse.StatusCode != HttpStatusCode.NotFound) { ContainerResponse retrivedContainerResponse = this.ClientContext.ResponseFactory.CreateContainerResponse( container, readResponse); if (!retrivedContainerResponse.Resource.PartitionKeyPath.Equals(containerProperties.PartitionKeyPath)) { throw new ArgumentException( string.Format( ClientResources.PartitionKeyPathConflict, containerProperties.PartitionKeyPath, containerProperties.Id, retrivedContainerResponse.Resource.PartitionKeyPath), nameof(containerProperties.PartitionKey)); } return(retrivedContainerResponse); } } this.ValidateContainerProperties(containerProperties); using (ResponseMessage createResponse = await this.CreateContainerStreamAsync( diagnosticsContext, containerProperties, throughputProperties, requestOptions, cancellationToken)) { if (createResponse.StatusCode != HttpStatusCode.Conflict) { return(this.ClientContext.ResponseFactory.CreateContainerResponse(container, createResponse)); } } // This second Read is to handle the race condition when 2 or more threads have Read the database and only one succeeds with Create // so for the remaining ones we should do a Read instead of throwing Conflict exception using (ResponseMessage readResponseAfterCreate = await container.ReadContainerStreamAsync( diagnosticsContext: diagnosticsContext, cancellationToken: cancellationToken)) { return(this.ClientContext.ResponseFactory.CreateContainerResponse(container, readResponseAfterCreate)); } }
public abstract Task <Documents.ShouldRetryResult> HandleSplitAsync( ContainerCore containerCore, ResponseMessage responseMessage, CancellationToken cancellationToken);
private async Task<ResponseMessage> ReadNextInternalAsync( CosmosDiagnosticsContext diagnostics, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); Stream stream = null; OperationType operation = OperationType.ReadFeed; if (this.querySpec != null) { stream = this.clientContext.SerializerCore.ToStreamSqlQuerySpec(this.querySpec, this.resourceType); operation = OperationType.Query; } if (this.feedTokenInternal == null) { TryCatch<FeedTokenInternal> tryCatchFeedTokeninternal = await this.TryInitializeFeedTokenAsync(cancellationToken); if (!tryCatchFeedTokeninternal.Succeeded) { if (tryCatchFeedTokeninternal.Exception.InnerException is CosmosException cosmosException) { return cosmosException.ToCosmosResponseMessage(new RequestMessage(method: null, requestUri: null, diagnosticsContext: diagnostics)); } return CosmosExceptionFactory.CreateInternalServerErrorException( message: tryCatchFeedTokeninternal.Exception.InnerException.Message, innerException: tryCatchFeedTokeninternal.Exception.InnerException, diagnosticsContext: diagnostics).ToCosmosResponseMessage(new RequestMessage(method: null, requestUri: null, diagnosticsContext: diagnostics)); } this.feedTokenInternal = tryCatchFeedTokeninternal.Result; } ResponseMessage response = await this.clientContext.ProcessResourceOperationStreamAsync( resourceUri: this.resourceLink, resourceType: this.resourceType, operationType: operation, requestOptions: this.requestOptions, cosmosContainerCore: null, partitionKey: this.requestOptions?.PartitionKey, streamPayload: stream, requestEnricher: request => { QueryRequestOptions.FillContinuationToken(request, this.ContinuationToken); if (this.querySpec != null) { request.Headers.Add(HttpConstants.HttpHeaders.ContentType, MediaTypes.QueryJson); request.Headers.Add(HttpConstants.HttpHeaders.IsQuery, bool.TrueString); } this.feedTokenInternal?.EnrichRequest(request); }, diagnosticsContext: diagnostics, cancellationToken: cancellationToken); // Retry in case of splits or other scenarios only on partitioned resources if (this.containerCore != null && await this.feedTokenInternal.ShouldRetryAsync(this.containerCore, response, cancellationToken)) { return await this.ReadNextInternalAsync(diagnostics, cancellationToken); } if (response.IsSuccessStatusCode) { this.feedTokenInternal.UpdateContinuation(response.Headers.ContinuationToken); this.ContinuationToken = this.feedTokenInternal.GetContinuation(); this.hasMoreResultsInternal = !this.feedTokenInternal.IsDone; } else { this.hasMoreResultsInternal = false; } return response; }
public abstract Documents.ShouldRetryResult HandleChangeFeedNotModified(ResponseMessage responseMessage);
public override FeedResponse <T> CreateQueryFeedUserTypeResponse <T>( ResponseMessage responseMessage) { return(this.CreateQueryFeedResponseHelper <T>( responseMessage)); }
public T ToObjectpublic <T>(ResponseMessage responseMessage) { if (responseMessage.Content == null) { return(default);
internal static async Task <TransactionalBatchResponse> FromResponseMessageAsync( ResponseMessage responseMessage, ServerBatchRequest serverRequest, CosmosSerializerCore serializer, bool shouldPromoteOperationStatus = true) { 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); } return(response); } }
public override FeedResponse <T> CreateItemFeedResponse <T>(ResponseMessage responseMessage) { return(this.CreateQueryFeedResponseHelper <T>( responseMessage, Documents.ResourceType.Document)); }
private static async Task <TransactionalBatchResponse> PopulateFromContentAsync( Stream content, ResponseMessage responseMessage, ServerBatchRequest serverRequest, CosmosSerializerCore serializer, bool shouldPromoteOperationStatus) { List <TransactionalBatchOperationResult> results = new List <TransactionalBatchOperationResult>(); // content is ensured to be seekable in caller. int resizerInitialCapacity = (int)content.Length; Result res = await content.ReadRecordIOAsync( record => { Result r = TransactionalBatchOperationResult.ReadOperationResult(record, out TransactionalBatchOperationResult operationResult); if (r != Result.Success) { return(r); } results.Add(operationResult); return(r); }, resizer : new MemorySpanResizer <byte>(resizerInitialCapacity)); if (res != Result.Success) { return(null); } HttpStatusCode responseStatusCode = responseMessage.StatusCode; SubStatusCodes responseSubStatusCode = responseMessage.Headers.SubStatusCode; // Promote the operation error status as the Batch response error status if we have a MultiStatus response // to provide users with status codes they are used to. if ((int)responseMessage.StatusCode == (int)StatusCodes.MultiStatus && shouldPromoteOperationStatus) { foreach (TransactionalBatchOperationResult result in results) { if ((int)result.StatusCode != (int)StatusCodes.FailedDependency) { responseStatusCode = result.StatusCode; responseSubStatusCode = result.SubStatusCode; break; } } } TransactionalBatchResponse response = new TransactionalBatchResponse( responseStatusCode, responseSubStatusCode, responseMessage.ErrorMessage, responseMessage.Headers.RequestCharge, responseMessage.Headers.RetryAfter, responseMessage.Headers.ActivityId, responseMessage.DiagnosticsContext, serverRequest.Operations, serializer); response.results = results; return(response); }
private async Task <ResponseMessage> ReadNextInternalAsync( CosmosDiagnosticsContext diagnostics, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); ResponseMessage responseMessage = await this.clientContext.ProcessResourceOperationStreamAsync( resourceUri : this.containerCore.LinkUri, resourceType : ResourceType.Document, operationType : OperationType.ReadFeed, requestOptions : this.queryRequestOptions, cosmosContainerCore : this.containerCore, partitionKey : this.queryRequestOptions?.PartitionKey, streamPayload : null, requestEnricher : request => { FeedRangeVisitor feedRangeVisitor = new FeedRangeVisitor(request); this.FeedRangeInternal.Accept(feedRangeVisitor); this.FeedRangeContinuation.Accept(feedRangeVisitor, QueryRequestOptions.FillContinuationToken); }, diagnosticsContext : diagnostics, cancellationToken : cancellationToken); ShouldRetryResult shouldRetryOnSplit = await this.FeedRangeContinuation.HandleSplitAsync(this.containerCore, responseMessage, cancellationToken); if (shouldRetryOnSplit.ShouldRetry) { return(await this.ReadNextInternalAsync(diagnostics, cancellationToken)); } if (responseMessage.Content != null) { // Rewrite the payload to be in the specified format. // If it's already in the correct format, then the following will be a memcpy. MemoryStream memoryStream; if (responseMessage.Content is MemoryStream responseContentAsMemoryStream) { memoryStream = responseContentAsMemoryStream; } else { memoryStream = new MemoryStream(); await responseMessage.Content.CopyToAsync(memoryStream); } ReadOnlyMemory <byte> buffer; if (memoryStream.TryGetBuffer(out ArraySegment <byte> segment)) { buffer = segment.Array.AsMemory().Slice(start: segment.Offset, length: segment.Count); } else { buffer = memoryStream.ToArray(); } IJsonReader jsonReader = JsonReader.Create(buffer); IJsonWriter jsonWriter; if (this.queryRequestOptions?.CosmosSerializationFormatOptions != null) { jsonWriter = this.queryRequestOptions.CosmosSerializationFormatOptions.CreateCustomWriterCallback(); } else { jsonWriter = NewtonsoftToCosmosDBWriter.CreateTextWriter(); } jsonWriter.WriteAll(jsonReader); ReadOnlyMemory <byte> result = jsonWriter.GetResult(); MemoryStream rewrittenMemoryStream; if (MemoryMarshal.TryGetArray(result, out ArraySegment <byte> rewrittenSegment)) { rewrittenMemoryStream = new MemoryStream(rewrittenSegment.Array, index: rewrittenSegment.Offset, count: rewrittenSegment.Count); } else { rewrittenMemoryStream = new MemoryStream(result.ToArray()); } responseMessage.Content = rewrittenMemoryStream; } if (responseMessage.IsSuccessStatusCode) { this.FeedRangeContinuation.ReplaceContinuation(responseMessage.Headers.ContinuationToken); this.hasMoreResultsInternal = !this.FeedRangeContinuation.IsDone; return(FeedRangeResponse.CreateSuccess(responseMessage, this.FeedRangeContinuation)); } else { this.hasMoreResultsInternal = false; return(FeedRangeResponse.CreateFailure(responseMessage)); } }
// Extracted partition key might be invalid as CollectionCache might be stale. // Stale collection cache is refreshed through PartitionKeyMismatchRetryPolicy // and partition-key is extracted again. internal async Task <ResponseMessage> ExtractPartitionKeyAndProcessItemStreamAsync <T>( PartitionKey?partitionKey, string itemId, T item, OperationType operationType, RequestOptions requestOptions, CancellationToken cancellationToken) { CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(requestOptions); using (diagnosticsContext.CreateOverallScope("ItemStream")) { Stream itemStream; using (diagnosticsContext.CreateScope("ItemSerialize")) { itemStream = this.ClientContext.SerializerCore.ToStream <T>(item); } // User specified PK value, no need to extract it if (partitionKey.HasValue) { return(await this.ProcessItemStreamAsync( partitionKey, itemId, itemStream, operationType, requestOptions, diagnosticsScope : diagnosticsContext, cancellationToken : cancellationToken)); } PartitionKeyMismatchRetryPolicy requestRetryPolicy = null; while (true) { using (diagnosticsContext.CreateScope("ExtractPkValue")) { partitionKey = await this.GetPartitionKeyValueFromStreamAsync(itemStream, cancellationToken); } ResponseMessage responseMessage = await this.ProcessItemStreamAsync( partitionKey, itemId, itemStream, operationType, requestOptions, diagnosticsScope : diagnosticsContext, cancellationToken : cancellationToken); if (responseMessage.IsSuccessStatusCode) { return(responseMessage); } if (requestRetryPolicy == null) { requestRetryPolicy = new PartitionKeyMismatchRetryPolicy(await this.ClientContext.DocumentClient.GetCollectionCacheAsync(), null); } ShouldRetryResult retryResult = await requestRetryPolicy.ShouldRetryAsync(responseMessage, cancellationToken); if (!retryResult.ShouldRetry) { return(responseMessage); } } } }
public void EnsureSuccessStatusCode_DontThrowOnSuccess() { ResponseMessage responseMessage = new ResponseMessage(HttpStatusCode.OK); responseMessage.EnsureSuccessStatusCode(); }
public async Task <ContainerResponse> CreateContainerIfNotExistsAsync( CosmosDiagnosticsContext diagnosticsContext, ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions, ITrace trace, CancellationToken cancellationToken) { if (containerProperties == null) { throw new ArgumentNullException(nameof(containerProperties)); } this.ValidateContainerProperties(containerProperties); double totalRequestCharge = 0; ContainerCore container = (ContainerCore)this.GetContainer(containerProperties.Id); using (ResponseMessage readResponse = await container.ReadContainerStreamAsync( diagnosticsContext: diagnosticsContext, requestOptions: requestOptions, trace: trace, cancellationToken: cancellationToken)) { totalRequestCharge = readResponse.Headers.RequestCharge; if (readResponse.StatusCode != HttpStatusCode.NotFound) { ContainerResponse retrivedContainerResponse = this.ClientContext.ResponseFactory.CreateContainerResponse( container, readResponse); if (containerProperties.PartitionKey.Kind != Documents.PartitionKind.MultiHash) { if (!retrivedContainerResponse.Resource.PartitionKeyPath.Equals(containerProperties.PartitionKeyPath)) { throw new ArgumentException( string.Format( ClientResources.PartitionKeyPathConflict, containerProperties.PartitionKeyPath, containerProperties.Id, retrivedContainerResponse.Resource.PartitionKeyPath), nameof(containerProperties.PartitionKey)); } } #if INTERNAL || SUBPARTITIONING else { IReadOnlyList <string> retrivedPartitionKeyPaths = retrivedContainerResponse.Resource.PartitionKeyPaths; IReadOnlyList <string> receivedPartitionKeyPaths = containerProperties.PartitionKeyPaths; if (retrivedPartitionKeyPaths.Count != receivedPartitionKeyPaths.Count || !Enumerable.SequenceEqual(retrivedPartitionKeyPaths, receivedPartitionKeyPaths)) { throw new ArgumentException( string.Format( ClientResources.PartitionKeyPathConflict, string.Join(",", containerProperties.PartitionKeyPaths), containerProperties.Id, string.Join(",", retrivedContainerResponse.Resource.PartitionKeyPaths)), nameof(containerProperties.PartitionKey)); } } #endif return(retrivedContainerResponse); } } this.ValidateContainerProperties(containerProperties); using (ResponseMessage createResponse = await this.CreateContainerStreamAsync( diagnosticsContext, containerProperties, throughputProperties, requestOptions, trace, cancellationToken)) { totalRequestCharge += createResponse.Headers.RequestCharge; createResponse.Headers.RequestCharge = totalRequestCharge; if (createResponse.StatusCode != HttpStatusCode.Conflict) { return(this.ClientContext.ResponseFactory.CreateContainerResponse(container, createResponse)); } } // This second Read is to handle the race condition when 2 or more threads have Read the database and only one succeeds with Create // so for the remaining ones we should do a Read instead of throwing Conflict exception using (ResponseMessage readResponseAfterCreate = await container.ReadContainerStreamAsync( diagnosticsContext: diagnosticsContext, requestOptions: requestOptions, trace: trace, cancellationToken: cancellationToken)) { totalRequestCharge += readResponseAfterCreate.Headers.RequestCharge; readResponseAfterCreate.Headers.RequestCharge = totalRequestCharge; return(this.ClientContext.ResponseFactory.CreateContainerResponse(container, readResponseAfterCreate)); } }
public void EnsureSuccessStatusCode_ThrowsOnFailure() { ResponseMessage responseMessage = new ResponseMessage(HttpStatusCode.NotFound); Assert.ThrowsException <CosmosException>(() => responseMessage.EnsureSuccessStatusCode()); }
// Extracted partition key might be invalid as CollectionCache might be stale. // Stale collection cache is refreshed through PartitionKeyMismatchRetryPolicy // and partition-key is extracted again. private async Task <ResponseMessage> ExtractPartitionKeyAndProcessItemStreamAsync <T>( PartitionKey?partitionKey, string itemId, T item, OperationType operationType, ItemRequestOptions requestOptions, CosmosDiagnosticsContext diagnosticsContext, CancellationToken cancellationToken) { if (diagnosticsContext == null) { throw new ArgumentNullException(nameof(diagnosticsContext)); } Stream itemStream; using (diagnosticsContext.CreateScope("ItemSerialize")) { itemStream = this.ClientContext.SerializerCore.ToStream <T>(item); } // User specified PK value, no need to extract it if (partitionKey.HasValue) { PartitionKeyDefinition pKeyDefinition = await this.GetPartitionKeyDefinitionAsync(); if (partitionKey.HasValue && partitionKey.Value != PartitionKey.None && partitionKey.Value.InternalKey.Components.Count != pKeyDefinition.Paths.Count) { throw new ArgumentException(RMResources.MissingPartitionKeyValue); } return(await this.ProcessItemStreamAsync( partitionKey, itemId, itemStream, operationType, requestOptions, diagnosticsContext : diagnosticsContext, cancellationToken : cancellationToken)); } PartitionKeyMismatchRetryPolicy requestRetryPolicy = null; while (true) { using (diagnosticsContext.CreateScope("ExtractPkValue")) { partitionKey = await this.GetPartitionKeyValueFromStreamAsync(itemStream, cancellationToken); } ResponseMessage responseMessage = await this.ProcessItemStreamAsync( partitionKey, itemId, itemStream, operationType, requestOptions, diagnosticsContext : diagnosticsContext, cancellationToken : cancellationToken); if (responseMessage.IsSuccessStatusCode) { return(responseMessage); } if (requestRetryPolicy == null) { requestRetryPolicy = new PartitionKeyMismatchRetryPolicy(await this.ClientContext.DocumentClient.GetCollectionCacheAsync(), null); } ShouldRetryResult retryResult = await requestRetryPolicy.ShouldRetryAsync(responseMessage, cancellationToken); if (!retryResult.ShouldRetry) { return(responseMessage); } } }
private static TryCatch <QueryPage> 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) { CosmosException exception; if (cosmosResponseMessage.CosmosException != null) { exception = cosmosResponseMessage.CosmosException; } else { exception = new CosmosException( cosmosResponseMessage.ErrorMessage, cosmosResponseMessage.StatusCode, (int)cosmosResponseMessage.Headers.SubStatusCode, cosmosResponseMessage.Headers.ActivityId, cosmosResponseMessage.Headers.RequestCharge); } return(TryCatch <QueryPage> .FromException(exception)); } if (!(cosmosResponseMessage.Content is MemoryStream memoryStream)) { memoryStream = new MemoryStream(); cosmosResponseMessage.Content.CopyTo(memoryStream); } long responseLengthBytes = memoryStream.Length; CosmosArray documents = CosmosQueryClientCore.ParseElementsFromRestStream( memoryStream, resourceType, requestOptions.CosmosSerializationFormatOptions); CosmosQueryExecutionInfo cosmosQueryExecutionInfo; if (cosmosResponseMessage.Headers.TryGetValue(QueryExecutionInfoHeader, out string queryExecutionInfoString)) { cosmosQueryExecutionInfo = JsonConvert.DeserializeObject <CosmosQueryExecutionInfo>(queryExecutionInfoString); } else { cosmosQueryExecutionInfo = default; } QueryState queryState; if (cosmosResponseMessage.Headers.ContinuationToken != null) { queryState = new QueryState(CosmosString.Create(cosmosResponseMessage.Headers.ContinuationToken)); } else { queryState = default; } QueryPage response = new QueryPage( documents, cosmosResponseMessage.Headers.RequestCharge, cosmosResponseMessage.Headers.ActivityId, responseLengthBytes, cosmosQueryExecutionInfo, disallowContinuationTokenMessage: null, queryState); return(TryCatch <QueryPage> .FromResult(response)); } }
internal static async Task <BatchResponse> FromResponseMessageAsync( ResponseMessage responseMessage, ServerBatchRequest serverRequest, CosmosSerializer serializer) { using (responseMessage) { BatchResponse response = null; if (responseMessage.IsSuccessStatusCode && responseMessage.Content != null) { response = await BatchResponse.PopulateFromContentAsync(responseMessage, serverRequest, serializer); if (response == null) { // Convert any payload read failures as InternalServerError response = new BatchResponse( HttpStatusCode.InternalServerError, SubStatusCodes.Unknown, ClientResources.ServerResponseDeserializationFailure, responseMessage.Headers.RequestCharge, responseMessage.Headers.RetryAfter, responseMessage.Headers.ActivityId, serverRequest, serializer); } } else { response = new BatchResponse( responseMessage.StatusCode, responseMessage.Headers.SubStatusCode, responseMessage.ErrorMessage, responseMessage.Headers.RequestCharge, responseMessage.Headers.RetryAfter, responseMessage.Headers.ActivityId, serverRequest, 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 BatchResponse( HttpStatusCode.InternalServerError, SubStatusCodes.Unknown, ClientResources.InvalidServerResponse, responseMessage.Headers.RequestCharge, responseMessage.Headers.RetryAfter, responseMessage.Headers.ActivityId, serverRequest, 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.results = new List <BatchOperationResult>(); for (int i = 0; i < serverRequest.Operations.Count; i++) { response.results.Add( new BatchOperationResult(response.StatusCode) { SubStatusCode = response.SubStatusCode, RetryAfter = TimeSpan.FromMilliseconds(retryAfterMilliseconds), }); } } return(response); } }
private async Task <ResponseMessage> ReadNextInternalAsync( CosmosDiagnosticsContext diagnostics, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); Stream stream = null; OperationType operation = OperationType.ReadFeed; if (this.querySpec != null) { stream = this.clientContext.SerializerCore.ToStreamSqlQuerySpec(this.querySpec, this.resourceType); operation = OperationType.Query; } ResponseMessage responseMessage = await this.clientContext.ProcessResourceOperationStreamAsync( resourceUri : this.containerCore.LinkUri, resourceType : this.resourceType, operationType : operation, requestOptions : this.queryRequestOptions, cosmosContainerCore : this.containerCore, partitionKey : this.queryRequestOptions?.PartitionKey, streamPayload : stream, requestEnricher : request => { // FeedRangeContinuationRequestMessagePopulatorVisitor needs to run before FeedRangeRequestMessagePopulatorVisitor, // since they both set EPK range headers and in the case of split we need to run on the child range and not the parent range. FeedRangeContinuationRequestMessagePopulatorVisitor feedRangeContinuationVisitor = new FeedRangeContinuationRequestMessagePopulatorVisitor( request, QueryRequestOptions.FillContinuationToken); this.FeedRangeContinuation.Accept(feedRangeContinuationVisitor); FeedRangeRequestMessagePopulatorVisitor feedRangeVisitor = new FeedRangeRequestMessagePopulatorVisitor(request); this.FeedRangeInternal.Accept(feedRangeVisitor); if (this.querySpec != null) { request.Headers.Add(HttpConstants.HttpHeaders.ContentType, MediaTypes.QueryJson); request.Headers.Add(HttpConstants.HttpHeaders.IsQuery, bool.TrueString); } }, diagnosticsContext : diagnostics, cancellationToken : cancellationToken); ShouldRetryResult shouldRetryOnSplit = await this.FeedRangeContinuation.HandleSplitAsync(this.containerCore, responseMessage, cancellationToken); if (shouldRetryOnSplit.ShouldRetry) { return(await this.ReadNextInternalAsync(diagnostics, cancellationToken)); } if (responseMessage.Content != null) { await CosmosElementSerializer.RewriteStreamAsTextAsync(responseMessage, this.queryRequestOptions); } if (responseMessage.IsSuccessStatusCode) { this.FeedRangeContinuation.ReplaceContinuation(responseMessage.Headers.ContinuationToken); this.hasMoreResultsInternal = !this.FeedRangeContinuation.IsDone; return(FeedRangeResponse.CreateSuccess(responseMessage, this.FeedRangeContinuation)); } else { this.hasMoreResultsInternal = false; return(FeedRangeResponse.CreateFailure(responseMessage)); } }