Esempio n. 1
0
        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));
        }
Esempio n. 2
0
        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);
        }
Esempio n. 6
0
 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;
        }
Esempio n. 9
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 = (ContainerCore)leaseContainer;
            return(this);
        }
Esempio n. 10
0
 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;
 }
Esempio n. 11
0
        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);
        }
Esempio n. 13
0
        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();
        }
Esempio n. 15
0
        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;
 }
Esempio n. 18
0
        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));
        }
Esempio n. 19
0
 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);
Esempio n. 23
0
        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);
Esempio n. 25
0
 internal override BatchAsyncContainerExecutor GetExecutorForContainer(ContainerCore container)
 {
     this.ThrowIfDisposed();
     return(this.batchExecutorCache.GetExecutorForContainer(container, this));
 }
Esempio n. 26
0
        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));
            }
        }