public override Task <CosmosResponseMessage> SendAsync(
            CosmosRequestMessage request,
            CancellationToken cancellationToken)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            RequestOptions promotedRequestOptions = request.RequestOptions;

            if (promotedRequestOptions != null)
            {
                // Fill request options
                promotedRequestOptions.FillRequestOptions(request);

                // Validate the request consistency compatibility with account consistency
                // Type based access context for requested consistency preferred for performance
                Cosmos.ConsistencyLevel?consistencyLevel = null;
                if (promotedRequestOptions is ItemRequestOptions)
                {
                    consistencyLevel = (promotedRequestOptions as ItemRequestOptions).ConsistencyLevel;
                }
                else if (promotedRequestOptions is QueryRequestOptions)
                {
                    consistencyLevel = (promotedRequestOptions as QueryRequestOptions).ConsistencyLevel;
                }
                else if (promotedRequestOptions is StoredProcedureRequestOptions)
                {
                    consistencyLevel = (promotedRequestOptions as StoredProcedureRequestOptions).ConsistencyLevel;
                }

                if (consistencyLevel.HasValue)
                {
                    if (!ValidationHelpers.ValidateConsistencyLevel(this.client.AccountConsistencyLevel, consistencyLevel.Value))
                    {
                        throw new ArgumentException(string.Format(
                                                        CultureInfo.CurrentUICulture,
                                                        RMResources.InvalidConsistencyLevel,
                                                        consistencyLevel.Value.ToString(),
                                                        this.client.AccountConsistencyLevel));
                    }
                }
            }

            return(this.client.DocumentClient.EnsureValidClientAsync()
                   .ContinueWith(task => request.AssertPartitioningDetailsAsync(this.client, cancellationToken))
                   .ContinueWith(task =>
            {
                if (task.IsFaulted)
                {
                    throw task.Exception;
                }

                this.FillMultiMasterContext(request);
                return base.SendAsync(request, cancellationToken);
            })
                   .Unwrap());
        }
        public static CosmosClient CreateMockCosmosClient(
            Action <CosmosClientBuilder> customizeClientBuilder = null,
            Cosmos.ConsistencyLevel?accountConsistencyLevel     = null)
        {
            DocumentClient      documentClient      = accountConsistencyLevel.HasValue ? new MockDocumentClient(accountConsistencyLevel.Value) : new MockDocumentClient();
            CosmosClientBuilder cosmosClientBuilder = new CosmosClientBuilder("http://localhost", MockCosmosUtil.RandomInvalidCorrectlyFormatedAuthKey);

            customizeClientBuilder?.Invoke(cosmosClientBuilder);

            return(cosmosClientBuilder.Build(documentClient));
        }
示例#3
0
        private static string GetConsistencyString(Cosmos.ConsistencyLevel?consistency)
        {
            if (consistency == null)
            {
                return(null);
            }

            return(consistency switch
            {
                Cosmos.ConsistencyLevel.Strong => "STRONG",
                Cosmos.ConsistencyLevel.Session => "SESSION",
                Cosmos.ConsistencyLevel.Eventual => "EVENTUAL",
                Cosmos.ConsistencyLevel.ConsistentPrefix => "CONSISTENTPREFIX",
                Cosmos.ConsistencyLevel.BoundedStaleness => "BOUNDEDSTALENESS",
                _ => consistency.ToString().ToUpper(),
            });
示例#4
0
 internal OperationInfo(string regionsContacted,
                        long?responseSizeInBytes,
                        Cosmos.ConsistencyLevel?consistency,
                        string databaseName,
                        string containerName,
                        OperationType?operation,
                        ResourceType?resource,
                        int?statusCode)
 {
     this.RegionsContacted    = regionsContacted;
     this.ResponseSizeInBytes = responseSizeInBytes;
     if (responseSizeInBytes != null)
     {
         this.GreaterThan1Kb = responseSizeInBytes > ClientTelemetryOptions.OneKbToBytes;
     }
     this.Consistency   = OperationInfo.GetConsistencyString(consistency);
     this.DatabaseName  = databaseName;
     this.ContainerName = containerName;
     this.Operation     = operation?.ToOperationTypeString();
     this.Resource      = resource?.ToResourceTypeString();
     this.StatusCode    = statusCode;
 }
示例#5
0
        private async Task ValidateAndSetConsistencyLevelAsync(RequestMessage requestMessage)
        {
            // Validate the request consistency compatibility with account consistency
            // Type based access context for requested consistency preferred for performance
            Cosmos.ConsistencyLevel?consistencyLevel       = null;
            RequestOptions          promotedRequestOptions = requestMessage.RequestOptions;

            if (promotedRequestOptions != null && promotedRequestOptions.BaseConsistencyLevel.HasValue)
            {
                consistencyLevel = promotedRequestOptions.BaseConsistencyLevel;
            }
            else if (this.RequestedClientConsistencyLevel.HasValue)
            {
                consistencyLevel = this.RequestedClientConsistencyLevel;
            }

            if (consistencyLevel.HasValue)
            {
                if (!this.AccountConsistencyLevel.HasValue)
                {
                    this.AccountConsistencyLevel = await this.client.GetAccountConsistencyLevelAsync();
                }

                if (ValidationHelpers.IsValidConsistencyLevelOverwrite(this.AccountConsistencyLevel.Value, consistencyLevel.Value))
                {
                    // ConsistencyLevel compatibility with back-end configuration will be done by RequestInvokeHandler
                    requestMessage.Headers.Add(HttpConstants.HttpHeaders.ConsistencyLevel, consistencyLevel.Value.ToString());
                }
                else
                {
                    throw new ArgumentException(string.Format(
                                                    CultureInfo.CurrentUICulture,
                                                    RMResources.InvalidConsistencyLevel,
                                                    consistencyLevel.Value.ToString(),
                                                    this.AccountConsistencyLevel));
                }
            }
        }
        public static CosmosClient CreateMockCosmosClient(
            Action <CosmosClientBuilder> customizeClientBuilder = null,
            Cosmos.ConsistencyLevel?accountConsistencyLevel     = null)
        {
            DocumentClient documentClient;

            if (accountConsistencyLevel.HasValue)
            {
                documentClient = new MockDocumentClient(accountConsistencyLevel.Value);
            }
            else
            {
                documentClient = new MockDocumentClient();
            }

            CosmosClientBuilder cosmosClientBuilder = new CosmosClientBuilder("http://localhost", Guid.NewGuid().ToString());

            if (customizeClientBuilder != null)
            {
                customizeClientBuilder(cosmosClientBuilder);
            }

            return(cosmosClientBuilder.Build(documentClient));
        }
示例#7
0
        public async Task <INameValueCollection> CreateCommonHeadersAsync(FeedOptions feedOptions)
        {
            INameValueCollection requestHeaders = new DictionaryNameValueCollection();

            Cosmos.ConsistencyLevel defaultConsistencyLevel = (Cosmos.ConsistencyLevel) await this.Client.GetDefaultConsistencyLevelAsync();

            Cosmos.ConsistencyLevel?desiredConsistencyLevel = (Cosmos.ConsistencyLevel?) await this.Client.GetDesiredConsistencyLevelAsync();

            if (!string.IsNullOrEmpty(feedOptions.SessionToken) && !ReplicatedResourceClient.IsReadingFromMaster(this.ResourceTypeEnum, OperationType.ReadFeed))
            {
                if (defaultConsistencyLevel == Cosmos.ConsistencyLevel.Session || (desiredConsistencyLevel.HasValue && desiredConsistencyLevel.Value == Cosmos.ConsistencyLevel.Session))
                {
                    // Query across partitions is not supported today. Master resources (for e.g., database)
                    // can span across partitions, whereas server resources (viz: collection, document and attachment)
                    // don't span across partitions. Hence, session token returned by one partition should not be used
                    // when quering resources from another partition.
                    // Since master resources can span across partitions, don't send session token to the backend.
                    // As master resources are sync replicated, we should always get consistent query result for master resources,
                    // irrespective of the chosen replica.
                    // For server resources, which don't span partitions, specify the session token
                    // for correct replica to be chosen for servicing the query result.
                    requestHeaders[HttpConstants.HttpHeaders.SessionToken] = feedOptions.SessionToken;
                }
            }

            requestHeaders[HttpConstants.HttpHeaders.Continuation] = feedOptions.RequestContinuationToken;
            requestHeaders[HttpConstants.HttpHeaders.IsQuery]      = bool.TrueString;

            // Flow the pageSize only when we are not doing client eval
            if (feedOptions.MaxItemCount.HasValue)
            {
                requestHeaders[HttpConstants.HttpHeaders.PageSize] = feedOptions.MaxItemCount.ToString();
            }

            requestHeaders[HttpConstants.HttpHeaders.EnableCrossPartitionQuery] = feedOptions.EnableCrossPartitionQuery.ToString();

            if (feedOptions.MaxDegreeOfParallelism != 0)
            {
                requestHeaders[HttpConstants.HttpHeaders.ParallelizeCrossPartitionQuery] = bool.TrueString;
            }

            if (this.feedOptions.EnableScanInQuery != null)
            {
                requestHeaders[HttpConstants.HttpHeaders.EnableScanInQuery] = this.feedOptions.EnableScanInQuery.ToString();
            }

            if (this.feedOptions.EmitVerboseTracesInQuery != null)
            {
                requestHeaders[HttpConstants.HttpHeaders.EmitVerboseTracesInQuery] = this.feedOptions.EmitVerboseTracesInQuery.ToString();
            }

            if (this.feedOptions.EnableLowPrecisionOrderBy != null)
            {
                requestHeaders[HttpConstants.HttpHeaders.EnableLowPrecisionOrderBy] = this.feedOptions.EnableLowPrecisionOrderBy.ToString();
            }

            if (!string.IsNullOrEmpty(this.feedOptions.FilterBySchemaResourceId))
            {
                requestHeaders[HttpConstants.HttpHeaders.FilterBySchemaResourceId] = this.feedOptions.FilterBySchemaResourceId;
            }

            if (this.feedOptions.ResponseContinuationTokenLimitInKb != null)
            {
                requestHeaders[HttpConstants.HttpHeaders.ResponseContinuationTokenLimitInKB] = this.feedOptions.ResponseContinuationTokenLimitInKb.ToString();
            }

            if (this.feedOptions.ConsistencyLevel.HasValue)
            {
                await this.Client.EnsureValidOverwriteAsync((Documents.ConsistencyLevel) feedOptions.ConsistencyLevel.Value);

                requestHeaders.Set(HttpConstants.HttpHeaders.ConsistencyLevel, this.feedOptions.ConsistencyLevel.Value.ToString());
            }
            else if (desiredConsistencyLevel.HasValue)
            {
                requestHeaders.Set(HttpConstants.HttpHeaders.ConsistencyLevel, desiredConsistencyLevel.Value.ToString());
            }

            if (this.feedOptions.EnumerationDirection.HasValue)
            {
                requestHeaders.Set(HttpConstants.HttpHeaders.EnumerationDirection, this.feedOptions.EnumerationDirection.Value.ToString());
            }

            if (this.feedOptions.ReadFeedKeyType.HasValue)
            {
                requestHeaders.Set(HttpConstants.HttpHeaders.ReadFeedKeyType, this.feedOptions.ReadFeedKeyType.Value.ToString());
            }

            if (this.feedOptions.StartId != null)
            {
                requestHeaders.Set(HttpConstants.HttpHeaders.StartId, this.feedOptions.StartId);
            }

            if (this.feedOptions.EndId != null)
            {
                requestHeaders.Set(HttpConstants.HttpHeaders.EndId, this.feedOptions.EndId);
            }

            if (this.feedOptions.StartEpk != null)
            {
                requestHeaders.Set(HttpConstants.HttpHeaders.StartEpk, this.feedOptions.StartEpk);
            }

            if (this.feedOptions.EndEpk != null)
            {
                requestHeaders.Set(HttpConstants.HttpHeaders.EndEpk, this.feedOptions.EndEpk);
            }

            if (this.feedOptions.PopulateQueryMetrics)
            {
                requestHeaders[HttpConstants.HttpHeaders.PopulateQueryMetrics] = bool.TrueString;
            }

            if (this.feedOptions.ForceQueryScan)
            {
                requestHeaders[HttpConstants.HttpHeaders.ForceQueryScan] = bool.TrueString;
            }

            if (this.feedOptions.MergeStaticId != null)
            {
                requestHeaders.Set(HttpConstants.HttpHeaders.MergeStaticId, this.feedOptions.MergeStaticId);
            }

            if (this.feedOptions.CosmosSerializationFormatOptions != null)
            {
                requestHeaders[HttpConstants.HttpHeaders.ContentSerializationFormat] = this.feedOptions.CosmosSerializationFormatOptions.ContentSerializationFormat;
            }
            else if (this.feedOptions.ContentSerializationFormat.HasValue)
            {
                requestHeaders[HttpConstants.HttpHeaders.ContentSerializationFormat] = this.feedOptions.ContentSerializationFormat.Value.ToString();
            }

            return(requestHeaders);
        }
示例#8
0
 public RequestInvokerHandler(CosmosClient client)
 {
     this.client = client;
     this.RequestedClientConsistencyLevel = this.client.ClientOptions.ConsistencyLevel;
 }