internal override Task <ResponseMessage> ProcessResourceOperationStreamAsync( Uri resourceUri, ResourceType resourceType, OperationType operationType, RequestOptions requestOptions, ContainerCore cosmosContainerCore, PartitionKey?partitionKey, string itemId, Stream streamPayload, Action <RequestMessage> requestEnricher, CosmosDiagnosticsContext diagnosticsContext, CancellationToken cancellationToken) { this.ThrowIfDisposed(); if (this.IsBulkOperationSupported(resourceType, operationType)) { if (!partitionKey.HasValue) { throw new ArgumentOutOfRangeException(nameof(partitionKey)); } if (requestEnricher != null) { throw new ArgumentException($"Bulk does not support {nameof(requestEnricher)}"); } return(this.ProcessResourceOperationAsBulkStreamAsync( resourceUri: resourceUri, resourceType: resourceType, operationType: operationType, requestOptions: requestOptions, cosmosContainerCore: cosmosContainerCore, partitionKey: partitionKey.Value, itemId: itemId, streamPayload: streamPayload, diagnosticsContext: diagnosticsContext, cancellationToken: cancellationToken)); } return(this.ProcessResourceOperationStreamAsync( resourceUri: resourceUri, resourceType: resourceType, operationType: operationType, requestOptions: requestOptions, cosmosContainerCore: cosmosContainerCore, partitionKey: partitionKey, streamPayload: streamPayload, requestEnricher: requestEnricher, diagnosticsContext: diagnosticsContext, cancellationToken: cancellationToken)); }
internal StandByFeedIteratorCore( CosmosClientContext clientContext, ContainerCore container, ChangeFeedRequestOptions options) { if (container == null) { throw new ArgumentNullException(nameof(container)); } this.clientContext = clientContext; this.container = container; this.changeFeedOptions = options; }
public BatchExecutor( ContainerCore container, PartitionKey partitionKey, IReadOnlyList <ItemBatchOperation> operations, RequestOptions batchOptions, CosmosDiagnosticsContext diagnosticsContext) { this.container = container; this.clientContext = this.container.ClientContext; this.inputOperations = operations; this.partitionKey = partitionKey; this.batchOptions = batchOptions; this.diagnosticsContext = diagnosticsContext; }
public override async Task <PartitionKey> GetPartitionKeyValueFromStreamAsync( Stream stream, CancellationToken cancellation = default(CancellationToken)) { if (!stream.CanSeek) { throw new ArgumentException("Stream needs to be seekable", nameof(stream)); } try { stream.Position = 0; if (!(stream is MemoryStream memoryStream)) { memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); } // TODO: Avoid copy IJsonNavigator jsonNavigator = JsonNavigator.Create(memoryStream.ToArray()); IJsonNavigatorNode jsonNavigatorNode = jsonNavigator.GetRootNode(); CosmosObject pathTraversal = CosmosObject.Create(jsonNavigator, jsonNavigatorNode); IReadOnlyList <IReadOnlyList <string> > tokenslist = await this.GetPartitionKeyPathTokensAsync(cancellation); List <CosmosElement> cosmosElementList = new List <CosmosElement>(tokenslist.Count); foreach (IReadOnlyList <string> tokenList in tokenslist) { CosmosElement element; if (ContainerCore.TryParseTokenListForElement(pathTraversal, tokenList, out element)) { cosmosElementList.Add(element); } else { cosmosElementList.Add(null); } } return(ContainerCore.CosmosElementToPartitionKeyObject(cosmosElementList)); } finally { // MemoryStream casting leverage might change position stream.Position = 0; } }
public override async Task <bool> ShouldRetryAsync( ContainerCore containerCore, ResponseMessage responseMessage, CancellationToken cancellationToken = default(CancellationToken)) { if (this.FeedTokenEPKRange != null) { return(await this.FeedTokenEPKRange.ShouldRetryAsync(containerCore, responseMessage, cancellationToken)); } if (responseMessage.IsSuccessStatusCode) { return(false); } bool partitionSplit = responseMessage.StatusCode == HttpStatusCode.Gone && (responseMessage.Headers.SubStatusCode == Documents.SubStatusCodes.PartitionKeyRangeGone || responseMessage.Headers.SubStatusCode == Documents.SubStatusCodes.CompletingSplit); if (partitionSplit) { string containerRid = await containerCore.GetRIDAsync(cancellationToken); Routing.PartitionKeyRangeCache partitionKeyRangeCache = await containerCore.ClientContext.DocumentClient.GetPartitionKeyRangeCacheAsync(); IReadOnlyList <Documents.PartitionKeyRange> keyRanges = await partitionKeyRangeCache.TryGetOverlappingRangesAsync( containerRid, new Documents.Routing.Range <string>( Documents.Routing.PartitionKeyInternal.MinimumInclusiveEffectivePartitionKey, Documents.Routing.PartitionKeyInternal.MaximumExclusiveEffectivePartitionKey, isMaxInclusive: false, isMinInclusive: true), forceRefresh : true); List <Documents.PartitionKeyRange> addedRanges = keyRanges.Where(range => range.Parents.Contains(this.PartitionKeyRangeId)).ToList(); if (addedRanges.Count == 0) { DefaultTrace.TraceError("FeedTokenPartitionKeyRange - Could not obtain children after split for {0}", this.PartitionKeyRangeId); return(false); } this.FeedTokenEPKRange = new FeedTokenEPKRange(containerRid, new Documents.Routing.Range <string>(addedRanges[0].MinInclusive, addedRanges[addedRanges.Count - 1].MaxExclusive, true, false), addedRanges.Select(range => FeedTokenEPKRange.CreateCompositeContinuationTokenForRange(range.MinInclusive, range.MaxExclusive, this.continuationToken)).ToList()); return(true); } return(false); }
public BatchExecutor( ContainerCore container, PartitionKey partitionKey, IReadOnlyList <ItemBatchOperation> operations, RequestOptions batchOptions, int maxServerRequestBodyLength, int maxServerRequestOperationCount) { this.container = container; this.clientContext = this.container.ClientContext; this.inputOperations = operations; this.partitionKey = partitionKey; this.batchOptions = batchOptions; this.maxServerRequestBodyLength = maxServerRequestBodyLength; this.maxServerRequestOperationCount = maxServerRequestOperationCount; }
public ItemBatchOperation( OperationType operationType, int operationIndex, ContainerCore containerCore, string id = null, Stream resourceStream = null, TransactionalBatchItemRequestOptions requestOptions = null) { this.OperationType = operationType; this.OperationIndex = operationIndex; this.ContainerCore = containerCore; this.Id = id; this.ResourceStream = resourceStream; this.RequestOptions = requestOptions; this.DiagnosticsContext = null; }
public ConflictsCore( CosmosClientContext clientContext, ContainerCore container) { if (clientContext == null) { throw new ArgumentNullException(nameof(clientContext)); } if (container == null) { throw new ArgumentNullException(nameof(container)); } this.container = container; this.clientContext = clientContext; }
/// <summary> /// Sets the Cosmos Container to hold the leases state /// </summary> /// <param name="leaseContainer">Instance of a Cosmos Container to hold the leases.</param> /// <returns>The instance of <see cref="ChangeFeedProcessorBuilder"/> to use.</returns> public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer) { if (leaseContainer == null) { throw new ArgumentNullException(nameof(leaseContainer)); } if (this.leaseContainer != null) { throw new InvalidOperationException("The builder already defined a lease container."); } if (this.LeaseStoreManager != null) { throw new InvalidOperationException("The builder already defined an in-memory lease container instance."); } this.leaseContainer = (ContainerCore)leaseContainer; return(this); }
internal ChangeFeedProcessorBuilder( string processorName, ContainerCore container, ChangeFeedProcessor changeFeedProcessor, Action <DocumentServiceLeaseStoreManager, ContainerCore, string, string, ChangeFeedLeaseOptions, ChangeFeedProcessorOptions, ContainerCore> applyBuilderConfiguration) { this.changeFeedLeaseOptions = new ChangeFeedLeaseOptions(); this.changeFeedLeaseOptions.LeasePrefix = processorName; this.monitoredContainer = container; this.changeFeedProcessor = changeFeedProcessor; this.applyBuilderConfiguration = applyBuilderConfiguration; }
internal ChangeFeedResultSetIteratorCore( CosmosClientContext clientContext, ContainerCore container, string continuationToken, int?maxItemCount, ChangeFeedRequestOptions options) { if (container == null) { throw new ArgumentNullException(nameof(container)); } this.clientContext = clientContext; this.container = container; this.changeFeedOptions = options; this.maxItemCount = maxItemCount; this.continuationToken = continuationToken; }
public override async Task <bool> ShouldRetryAsync( ContainerCore containerCore, ResponseMessage responseMessage, CancellationToken cancellationToken = default(CancellationToken)) { if (responseMessage.IsSuccessStatusCode) { this.initialNoResultsRange = null; return(false); } // If the current response is NotModified (ChangeFeed), try and skip to a next one if (responseMessage.StatusCode == HttpStatusCode.NotModified && this.CompositeContinuationTokens.Count > 1) { if (this.initialNoResultsRange == null) { this.initialNoResultsRange = this.currentToken.Range.Min; return(true); } return(!this.initialNoResultsRange.Equals(this.currentToken.Range.Min, StringComparison.OrdinalIgnoreCase)); } // Split handling bool partitionSplit = responseMessage.StatusCode == HttpStatusCode.Gone && (responseMessage.Headers.SubStatusCode == Documents.SubStatusCodes.PartitionKeyRangeGone || responseMessage.Headers.SubStatusCode == Documents.SubStatusCodes.CompletingSplit); if (partitionSplit) { Routing.PartitionKeyRangeCache partitionKeyRangeCache = await containerCore.ClientContext.DocumentClient.GetPartitionKeyRangeCacheAsync(); IReadOnlyList <Documents.PartitionKeyRange> resolvedRanges = await this.TryGetOverlappingRangesAsync(partitionKeyRangeCache, this.currentToken.Range.Min, this.currentToken.Range.Max, forceRefresh : true); if (resolvedRanges.Count > 0) { this.HandleSplit(resolvedRanges); } return(true); } return(false); }
private async Task <ResponseMessage> ProcessResourceOperationAsBulkStreamAsync( Uri resourceUri, ResourceType resourceType, OperationType operationType, RequestOptions requestOptions, ContainerCore cosmosContainerCore, PartitionKey partitionKey, string itemId, Stream streamPayload, Action <RequestMessage> requestEnricher, CancellationToken cancellationToken) { ItemRequestOptions itemRequestOptions = requestOptions as ItemRequestOptions; TransactionalBatchItemRequestOptions batchItemRequestOptions = TransactionalBatchItemRequestOptions.FromItemRequestOptions(itemRequestOptions); ItemBatchOperation itemBatchOperation = new ItemBatchOperation(operationType, /* index */ 0, partitionKey, itemId, streamPayload, batchItemRequestOptions); TransactionalBatchOperationResult batchOperationResult = await cosmosContainerCore.BatchExecutor.AddAsync(itemBatchOperation, itemRequestOptions, cancellationToken); return(batchOperationResult.ToResponseMessage()); }
internal ChangeFeedIteratorCore( ContainerCore container, ChangeFeedRequestOptions changeFeedRequestOptions) { if (container == null) { throw new ArgumentNullException(nameof(container)); } if (changeFeedRequestOptions != null && changeFeedRequestOptions.MaxItemCount.HasValue && changeFeedRequestOptions.MaxItemCount.Value <= 0) { throw new ArgumentOutOfRangeException(nameof(changeFeedRequestOptions.MaxItemCount)); } this.clientContext = container.ClientContext; this.container = container; this.changeFeedOptions = changeFeedRequestOptions ?? new ChangeFeedRequestOptions(); }
private ChangeFeedIteratorCore( ContainerCore container, ChangeFeedRequestOptions changeFeedRequestOptions) { if (changeFeedRequestOptions != null && changeFeedRequestOptions.MaxItemCount.HasValue && changeFeedRequestOptions.MaxItemCount.Value <= 0) { throw new ArgumentOutOfRangeException(nameof(changeFeedRequestOptions.MaxItemCount)); } this.container = container ?? throw new ArgumentNullException(nameof(container)); this.clientContext = container.ClientContext; this.changeFeedOptions = changeFeedRequestOptions ?? new ChangeFeedRequestOptions(); this.lazyContainerRid = new AsyncLazy <TryCatch <string> >(valueFactory: (innerCancellationToken) => { return(this.TryInitializeContainerRIdAsync(innerCancellationToken)); }); }
internal static async Task <T> ProcessResourceOperationAsync <T>( RequestInvokerHandler requestHandler, Uri resourceUri, ResourceType resourceType, OperationType operationType, RequestOptions requestOptions, ContainerCore cosmosContainerCore, PartitionKey?partitionKey, Stream streamPayload, Action <RequestMessage> requestEnricher, Func <ResponseMessage, T> responseCreator, CancellationToken cancellationToken) { if (requestHandler == null) { throw new ArgumentException(nameof(requestHandler)); } if (resourceUri == null) { throw new ArgumentNullException(nameof(resourceUri)); } if (responseCreator == null) { throw new ArgumentNullException(nameof(responseCreator)); } ResponseMessage response = await requestHandler.SendAsync( resourceUri, resourceType, operationType, requestOptions, cosmosContainerCore, partitionKey, streamPayload, requestEnricher, null, cancellationToken); return(responseCreator(response)); }
private FeedIteratorCore( ContainerCore containerCore, CosmosClientContext clientContext, Uri resourceLink, ResourceType resourceType, QueryDefinition queryDefinition, string continuationToken, FeedTokenInternal feedTokenInternal, QueryRequestOptions options) { this.resourceLink = resourceLink; this.containerCore = containerCore; this.clientContext = clientContext; this.resourceType = resourceType; this.querySpec = queryDefinition?.ToSqlQuerySpec(); this.feedTokenInternal = feedTokenInternal; this.ContinuationToken = continuationToken ?? this.feedTokenInternal?.GetContinuation(); this.requestOptions = options; this.hasMoreResultsInternal = true; }
public static ChangeFeedIteratorCore Create( ContainerCore container, FeedRangeInternal feedRangeInternal, string continuation, ChangeFeedRequestOptions changeFeedRequestOptions) { if (!string.IsNullOrEmpty(continuation)) { if (FeedRangeContinuation.TryParse(continuation, out FeedRangeContinuation feedRangeContinuation)) { return(new ChangeFeedIteratorCore(container, feedRangeContinuation, changeFeedRequestOptions)); } else { throw new ArgumentException(string.Format(ClientResources.FeedToken_UnknownFormat, continuation)); } } feedRangeInternal = feedRangeInternal ?? FeedRangeEPK.ForCompleteRange(); return(new ChangeFeedIteratorCore(container, feedRangeInternal, changeFeedRequestOptions)); }
internal override Task <ResponseMessage> ProcessResourceOperationStreamAsync( Uri resourceUri, ResourceType resourceType, OperationType operationType, RequestOptions requestOptions, ContainerCore cosmosContainerCore, PartitionKey?partitionKey, Stream streamPayload, Action <RequestMessage> requestEnricher, CancellationToken cancellationToken) { return(this.RequestHandler.SendAsync( resourceUri: resourceUri, resourceType: resourceType, operationType: operationType, requestOptions: requestOptions, cosmosContainerCore: cosmosContainerCore, partitionKey: partitionKey, streamPayload: streamPayload, requestEnricher: requestEnricher, cancellationToken: cancellationToken)); }
internal static FeedIteratorCore CreateForPartitionedResource( ContainerCore containerCore, Uri resourceLink, ResourceType resourceType, QueryDefinition queryDefinition, string continuationToken, FeedTokenInternal feedTokenInternal, QueryRequestOptions options) { if (containerCore == null) { throw new ArgumentNullException(nameof(containerCore)); } return new FeedIteratorCore( containerCore: containerCore, clientContext: containerCore.ClientContext, resourceLink: resourceLink, resourceType: resourceType, queryDefinition: queryDefinition, continuationToken: continuationToken, feedTokenInternal: feedTokenInternal, options: options); }
public abstract Task <Documents.ShouldRetryResult> HandleSplitAsync( ContainerCore containerCore, ResponseMessage responseMessage, CancellationToken cancellationToken);
internal abstract BatchAsyncContainerExecutor GetExecutorForContainer( ContainerCore container);
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); } }
public virtual Task <bool> ShouldRetryAsync( ContainerCore containerCore, ResponseMessage responseMessage, CancellationToken cancellationToken = default(CancellationToken)) => Task.FromResult(false);
internal override BatchAsyncContainerExecutor GetExecutorForContainer(ContainerCore container) { this.ThrowIfDisposed(); return(this.batchExecutorCache.GetExecutorForContainer(container, this)); }
public async Task <ContainerResponse> CreateContainerIfNotExistsAsync( 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( 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 PREVIEW 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( 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( requestOptions: requestOptions, trace: trace, cancellationToken: cancellationToken)) { totalRequestCharge += readResponseAfterCreate.Headers.RequestCharge; readResponseAfterCreate.Headers.RequestCharge = totalRequestCharge; return(this.ClientContext.ResponseFactory.CreateContainerResponse(container, readResponseAfterCreate)); } }
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 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)); } }