Exemple #1
0
        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);
        }
Exemple #3
0
        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);
            }
        }
Exemple #6
0
        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);
        }
Exemple #7
0
        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));
                }
            }
        }