Exemplo n.º 1
0
        /// <summary>
        /// Get the next set of results from the cosmos service
        /// </summary>
        /// <param name="cancellationToken">(Optional) <see cref="CancellationToken"/> representing request cancellation.</param>
        /// <returns>A query response from cosmos service</returns>
        public override Task <ResponseMessage> ReadNextAsync(CancellationToken cancellationToken = default)
        {
            CosmosDiagnosticsContext diagnostics = CosmosDiagnosticsContext.Create(this.requestOptions);

            using (diagnostics.CreateOverallScope("FeedReadNextAsync"))
            {
                return(this.ReadNextInternalAsync(diagnostics, cancellationToken));
            }
        }
        // Extracted partition key might be invalid as CollectionCache might be stale.
        // Stale collection cache is refreshed through PartitionKeyMismatchRetryPolicy
        // and partition-key is extracted again.
        internal async Task <ResponseMessage> ExtractPartitionKeyAndProcessItemStreamAsync <T>(
            PartitionKey?partitionKey,
            string itemId,
            T item,
            OperationType operationType,
            RequestOptions requestOptions,
            CancellationToken cancellationToken)
        {
            CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(requestOptions);

            using (diagnosticsContext.CreateOverallScope("ItemStream"))
            {
                Stream itemStream;
                using (diagnosticsContext.CreateScope("ItemSerialize"))
                {
                    itemStream = this.ClientContext.SerializerCore.ToStream <T>(item);
                }

                // User specified PK value, no need to extract it
                if (partitionKey.HasValue)
                {
                    return(await this.ProcessItemStreamAsync(
                               partitionKey,
                               itemId,
                               itemStream,
                               operationType,
                               requestOptions,
                               diagnosticsScope : diagnosticsContext,
                               cancellationToken : cancellationToken));
                }

                PartitionKeyMismatchRetryPolicy requestRetryPolicy = null;
                while (true)
                {
                    using (diagnosticsContext.CreateScope("ExtractPkValue"))
                    {
                        partitionKey = await this.GetPartitionKeyValueFromStreamAsync(itemStream, cancellationToken);
                    }

                    ResponseMessage responseMessage = await this.ProcessItemStreamAsync(
                        partitionKey,
                        itemId,
                        itemStream,
                        operationType,
                        requestOptions,
                        diagnosticsScope : diagnosticsContext,
                        cancellationToken : cancellationToken);

                    if (responseMessage.IsSuccessStatusCode)
                    {
                        return(responseMessage);
                    }

                    if (requestRetryPolicy == null)
                    {
                        requestRetryPolicy = new PartitionKeyMismatchRetryPolicy(await this.ClientContext.DocumentClient.GetCollectionCacheAsync(), null);
                    }

                    ShouldRetryResult retryResult = await requestRetryPolicy.ShouldRetryAsync(responseMessage, cancellationToken);

                    if (!retryResult.ShouldRetry)
                    {
                        return(responseMessage);
                    }
                }
            }
        }
        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);
            }
        }