private ChangeFeedIteratorCore(
            ContainerInternal 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));
            });
        }
Beispiel #2
0
        internal static async Task <T> ProcessResourceOperationAsync <T>(
            RequestInvokerHandler requestHandler,
            string resourceUri,
            ResourceType resourceType,
            OperationType operationType,
            RequestOptions requestOptions,
            ContainerInternal cosmosContainerCore,
            FeedRange feedRange,
            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,
                feedRange,
                streamPayload,
                requestEnricher,
                null,
                NoOpTrace.Singleton,
                cancellationToken);

            return(responseCreator(response));
        }
Beispiel #3
0
 internal ChangeFeedProcessorBuilder(
     string processorName,
     ContainerInternal container,
     ChangeFeedProcessor changeFeedProcessor,
     Action <DocumentServiceLeaseStoreManager,
             ContainerInternal,
             string,
             ChangeFeedLeaseOptions,
             ChangeFeedProcessorOptions,
             ContainerInternal> applyBuilderConfiguration)
 {
     this.changeFeedLeaseOptions = new ChangeFeedLeaseOptions
     {
         LeasePrefix = processorName
     };
     this.monitoredContainer        = container;
     this.changeFeedProcessor       = changeFeedProcessor;
     this.applyBuilderConfiguration = applyBuilderConfiguration;
 }
Beispiel #4
0
        /// <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 = (ContainerInternal)leaseContainer;
            return(this);
        }
        public static ChangeFeedIteratorCore Create(
            ContainerInternal 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));
        }
        public BatchAsyncContainerExecutor(
            ContainerInternal cosmosContainer,
            CosmosClientContext cosmosClientContext,
            int maxServerRequestOperationCount,
            int maxServerRequestBodyLength)
        {
            if (maxServerRequestOperationCount < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(maxServerRequestOperationCount));
            }

            if (maxServerRequestBodyLength < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(maxServerRequestBodyLength));
            }

            this.cosmosContainer                = cosmosContainer ?? throw new ArgumentNullException(nameof(cosmosContainer));
            this.cosmosClientContext            = cosmosClientContext;
            this.maxServerRequestBodyLength     = maxServerRequestBodyLength;
            this.maxServerRequestOperationCount = maxServerRequestOperationCount;
            this.timerWheel   = TimerWheel.CreateTimerWheel(BatchAsyncContainerExecutor.TimerWheelResolution, BatchAsyncContainerExecutor.TimerWheelBucketCount);
            this.retryOptions = cosmosClientContext.ClientOptions.GetConnectionPolicy().RetryOptions;
        }
        private async Task <ResponseMessage> ProcessItemStreamAsync(
            PartitionKey?partitionKey,
            string itemId,
            Stream streamPayload,
            OperationType operationType,
            ItemRequestOptions requestOptions,
            CosmosDiagnosticsContext diagnosticsContext,
            CancellationToken cancellationToken)
        {
            if (diagnosticsContext == null)
            {
                throw new ArgumentNullException(nameof(diagnosticsContext));
            }

            if (requestOptions != null && requestOptions.IsEffectivePartitionKeyRouting)
            {
                partitionKey = null;
            }

            ContainerInternal.ValidatePartitionKey(partitionKey, requestOptions);
            string resourceUri = this.GetResourceUri(requestOptions, operationType, itemId);

            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,
                diagnosticsContext : diagnosticsContext,
                cancellationToken : cancellationToken);

            return(responseMessage);
        }
 internal abstract BatchAsyncContainerExecutor GetExecutorForContainer(
     ContainerInternal container);
 public FeedRangePartitionKeyRangeExtractor(ContainerInternal container)
 {
     this.container = container ?? throw new ArgumentNullException(nameof(container));
 }
Beispiel #10
0
        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);

            ContainerInternal container    = (ContainerInternal)this.GetContainer(containerProperties.Id);
            ResponseMessage   readResponse = await this.ProcessResourceOperationStreamAsync(
                null,
                OperationType.Read,
                container.LinkUri,
                ResourceType.Collection,
                requestOptions,
                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);
            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(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
            ResponseMessage readResponseAfterCreate = await this.ProcessResourceOperationStreamAsync(
                null,
                OperationType.Read,
                container.LinkUri,
                ResourceType.Collection,
                requestOptions,
                cancellationToken);

            // Merge the previous message diagnostics
            createResponse.DiagnosticsContext.AddDiagnosticsInternal(readResponse.DiagnosticsContext);
            return(this.ClientContext.ResponseFactory.CreateContainerResponse(container, readResponseAfterCreate));
        }
 public abstract Task <Documents.ShouldRetryResult> HandleSplitAsync(
     ContainerInternal containerCore,
     ResponseMessage responseMessage,
     CancellationToken cancellationToken);
        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++)
                    {
                        ContainerInternal containerCore          = serverRequest.Operations[index].ContainerInternal;
                        TransactionalBatchOperationResult result = response.results[index];
                        result.ResourceStream = await containerCore.ClientContext.DecryptItemAsync(
                            result.ResourceStream,
                            (DatabaseInternal)containerCore.Database,
                            responseMessage.DiagnosticsContext,
                            cancellationToken);
                    }
                }

                return(response);
            }
        }