public BatchAsyncContainerExecutor GetExecutorForContainer( ContainerInternal container, CosmosClientContext cosmosClientContext) { if (!cosmosClientContext.ClientOptions.AllowBulkExecution) { throw new InvalidOperationException("AllowBulkExecution is not currently enabled."); } string containerLink = container.LinkUri.ToString(); if (this.executorsPerContainer.TryGetValue(containerLink, out BatchAsyncContainerExecutor executor)) { return(executor); } BatchAsyncContainerExecutor newExecutor = new BatchAsyncContainerExecutor( container, cosmosClientContext, Constants.MaxOperationsInDirectModeBatchRequest, Constants.MaxDirectModeBatchRequestBodySizeInBytes); if (!this.executorsPerContainer.TryAdd(containerLink, newExecutor)) { newExecutor.Dispose(); } return(this.executorsPerContainer[containerLink]); }
internal virtual async Task ValidateOperationAsync( ItemBatchOperation operation, ItemRequestOptions itemRequestOptions = null, CancellationToken cancellationToken = default) { if (itemRequestOptions != null) { if (itemRequestOptions.BaseConsistencyLevel.HasValue || itemRequestOptions.PreTriggers != null || itemRequestOptions.PostTriggers != null || itemRequestOptions.SessionToken != null) { throw new InvalidOperationException(ClientResources.UnsupportedBulkRequestOptions); } if (itemRequestOptions.DiagnosticContextFactory != null) { throw new ArgumentException("DiagnosticContext is not allowed when AllowBulkExecution is set to true"); } Debug.Assert(BatchAsyncContainerExecutor.ValidateOperationEPK(operation, itemRequestOptions)); } await operation.MaterializeResourceAsync(this.cosmosClientContext.SerializerCore, cancellationToken); }
private async Task <PartitionKeyRangeBatchExecutionResult> ExecuteAsync( PartitionKeyRangeServerBatchRequest serverRequest, CancellationToken cancellationToken) { CosmosDiagnosticsContext diagnosticsContext = new CosmosDiagnosticsContext(); CosmosDiagnosticScope limiterScope = diagnosticsContext.CreateScope("BatchAsyncContainerExecutor.Limiter"); SemaphoreSlim limiter = this.GetOrAddLimiterForPartitionKeyRange(serverRequest.PartitionKeyRangeId); using (await limiter.UsingWaitAsync(cancellationToken)) { limiterScope.Dispose(); using (Stream serverRequestPayload = serverRequest.TransferBodyStream()) { Debug.Assert(serverRequestPayload != null, "Server request payload expected to be non-null"); ResponseMessage responseMessage = await this.cosmosClientContext.ProcessResourceOperationStreamAsync( this.cosmosContainer.LinkUri, ResourceType.Document, OperationType.Batch, new RequestOptions(), cosmosContainerCore : this.cosmosContainer, partitionKey : null, streamPayload : serverRequestPayload, requestEnricher : requestMessage => BatchAsyncContainerExecutor.AddHeadersToRequestMessage(requestMessage, serverRequest.PartitionKeyRangeId), diagnosticsScope : diagnosticsContext, cancellationToken : cancellationToken).ConfigureAwait(false); using (diagnosticsContext.CreateScope("BatchAsyncContainerExecutor.ToResponse")) { TransactionalBatchResponse serverResponse = await TransactionalBatchResponse.FromResponseMessageAsync(responseMessage, serverRequest, this.cosmosClientContext.SerializerCore).ConfigureAwait(false); return(new PartitionKeyRangeBatchExecutionResult(serverRequest.PartitionKeyRangeId, serverRequest.Operations, serverResponse)); } } } }
public virtual async Task <TransactionalBatchOperationResult> AddAsync( ItemBatchOperation operation, ITrace trace, ItemRequestOptions itemRequestOptions = null, CancellationToken cancellationToken = default) { if (operation == null) { throw new ArgumentNullException(nameof(operation)); } await this.ValidateOperationAsync(operation, itemRequestOptions, cancellationToken); string resolvedPartitionKeyRangeId = await this.ResolvePartitionKeyRangeIdAsync( operation, trace, cancellationToken).ConfigureAwait(false); BatchAsyncStreamer streamer = this.GetOrAddStreamerForPartitionKeyRange(resolvedPartitionKeyRangeId); ItemBatchOperationContext context = new ItemBatchOperationContext( resolvedPartitionKeyRangeId, trace, BatchAsyncContainerExecutor.GetRetryPolicy(this.cosmosContainer, operation.OperationType, this.retryOptions)); operation.AttachContext(context); streamer.Add(operation); return(await context.OperationTask); }
internal async Task ValidateOperationAsync( ItemBatchOperation operation, ItemRequestOptions itemRequestOptions = null, CancellationToken cancellationToken = default(CancellationToken)) { if (itemRequestOptions != null) { if (itemRequestOptions.BaseConsistencyLevel.HasValue || itemRequestOptions.PreTriggers != null || itemRequestOptions.PostTriggers != null || itemRequestOptions.SessionToken != null) { throw new InvalidOperationException(ClientResources.UnsupportedBatchRequestOptions); } Debug.Assert(BatchAsyncContainerExecutor.ValidateOperationEPK(operation, itemRequestOptions)); } await operation.MaterializeResourceAsync(this.cosmosClientContext.CosmosSerializer, cancellationToken); int itemByteSize = operation.GetApproximateSerializedLength(); if (itemByteSize > this.maxServerRequestBodyLength) { throw new ArgumentException(RMResources.RequestTooLarge); } }
public virtual async Task <TransactionalBatchOperationResult> AddAsync( ItemBatchOperation operation, ITrace trace, ItemRequestOptions itemRequestOptions = null, CancellationToken cancellationToken = default) { if (operation == null) { throw new ArgumentNullException(nameof(operation)); } await this.ValidateOperationAsync(operation, itemRequestOptions, cancellationToken); string resolvedPartitionKeyRangeId = await this.ResolvePartitionKeyRangeIdAsync( operation, trace, cancellationToken).ConfigureAwait(false); BatchAsyncStreamer streamer = this.GetOrAddStreamerForPartitionKeyRange(resolvedPartitionKeyRangeId); ItemBatchOperationContext context = new ItemBatchOperationContext( resolvedPartitionKeyRangeId, trace, BatchAsyncContainerExecutor.GetRetryPolicy(this.cosmosContainer, operation.OperationType, this.retryOptions)); if (itemRequestOptions != null && itemRequestOptions.AddRequestHeaders != null) { // get the header value if any, passed by the encryption package. Headers encryptionHeaders = new Headers(); itemRequestOptions.AddRequestHeaders?.Invoke(encryptionHeaders); // make sure we set the Intended Collection Rid header when we have encrypted payload. // This primarily would allow CosmosDB Encryption package to detect change in container referenced by a Client // and prevent creating data with wrong Encryption Policy. if (encryptionHeaders.TryGetValue(HttpConstants.HttpHeaders.IsClientEncrypted, out string encrypted)) { context.IsClientEncrypted = bool.Parse(encrypted); if (context.IsClientEncrypted && encryptionHeaders.TryGetValue(WFConstants.BackendHeaders.IntendedCollectionRid, out string ridValue)) { context.IntendedCollectionRidValue = ridValue; } } } operation.AttachContext(context); streamer.Add(operation); return(await context.OperationTask); }
internal virtual async Task ValidateOperationAsync( ItemBatchOperation operation, ItemRequestOptions itemRequestOptions = null, CancellationToken cancellationToken = default(CancellationToken)) { if (itemRequestOptions != null) { if (itemRequestOptions.BaseConsistencyLevel.HasValue || itemRequestOptions.PreTriggers != null || itemRequestOptions.PostTriggers != null || itemRequestOptions.SessionToken != null) { throw new InvalidOperationException(ClientResources.UnsupportedBulkRequestOptions); } Debug.Assert(BatchAsyncContainerExecutor.ValidateOperationEPK(operation, itemRequestOptions)); } await operation.MaterializeResourceAsync(this.cosmosClientContext.CosmosSerializer, cancellationToken); }
private async Task <PartitionKeyRangeBatchExecutionResult> ExecuteAsync( PartitionKeyRangeServerBatchRequest serverRequest, ITrace trace, CancellationToken cancellationToken) { SemaphoreSlim limiter = this.GetOrAddLimiterForPartitionKeyRange(serverRequest.PartitionKeyRangeId); using (await limiter.UsingWaitAsync(trace, cancellationToken)) { using (Stream serverRequestPayload = serverRequest.TransferBodyStream()) { Debug.Assert(serverRequestPayload != null, "Server request payload expected to be non-null"); ResponseMessage responseMessage = await this.cosmosClientContext.ProcessResourceOperationStreamAsync( this.cosmosContainer.LinkUri, ResourceType.Document, OperationType.Batch, new RequestOptions(), cosmosContainerCore : this.cosmosContainer, feedRange : null, streamPayload : serverRequestPayload, requestEnricher : requestMessage => BatchAsyncContainerExecutor.AddHeadersToRequestMessage(requestMessage, serverRequest.PartitionKeyRangeId), trace : trace, cancellationToken : cancellationToken).ConfigureAwait(false); TransactionalBatchResponse serverResponse = await TransactionalBatchResponse.FromResponseMessageAsync( responseMessage, serverRequest, this.cosmosClientContext.SerializerCore, shouldPromoteOperationStatus : true, trace, cancellationToken).ConfigureAwait(false); return(new PartitionKeyRangeBatchExecutionResult( serverRequest.PartitionKeyRangeId, serverRequest.Operations, serverResponse)); } } }