public GatewayAddressCache(
            Uri serviceEndpoint,
            Protocol protocol,
            IAuthorizationTokenProvider tokenProvider,
            IServiceConfigurationReader serviceConfigReader,
            CosmosHttpClient httpClient,
            long suboptimalPartitionForceRefreshIntervalInSeconds = 600,
            bool enableTcpConnectionEndpointRediscovery           = false)
        {
            this.addressEndpoint                        = new Uri(serviceEndpoint + "/" + Paths.AddressPathSegment);
            this.protocol                               = protocol;
            this.tokenProvider                          = tokenProvider;
            this.serviceEndpoint                        = serviceEndpoint;
            this.serviceConfigReader                    = serviceConfigReader;
            this.serverPartitionAddressCache            = new AsyncCache <PartitionKeyRangeIdentity, PartitionAddressInformation>();
            this.suboptimalServerPartitionTimestamps    = new ConcurrentDictionary <PartitionKeyRangeIdentity, DateTime>();
            this.serverPartitionAddressToPkRangeIdMap   = new ConcurrentDictionary <ServerKey, HashSet <PartitionKeyRangeIdentity> >();
            this.suboptimalMasterPartitionTimestamp     = DateTime.MaxValue;
            this.enableTcpConnectionEndpointRediscovery = enableTcpConnectionEndpointRediscovery;

            this.suboptimalPartitionForceRefreshIntervalInSeconds = suboptimalPartitionForceRefreshIntervalInSeconds;

            this.httpClient = httpClient;

            this.protocolFilter =
                string.Format(CultureInfo.InvariantCulture,
                              GatewayAddressCache.protocolFilterFormat,
                              Constants.Properties.Protocol,
                              GatewayAddressCache.ProtocolString(this.protocol));
        }
 /// <summary>
 /// Task to collect virtual machine metadata information. using instance metedata service API.
 /// ref: https://docs.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service?tabs=windows
 /// Collects only application region and environment information
 /// </summary>
 /// <returns>Async Task</returns>
 internal static async Task <AzureVMMetadata> LoadAzureVmMetaDataAsync(CosmosHttpClient httpClient)
 {
     if (azMetadata == null)
     {
         DefaultTrace.TraceVerbose("Getting VM Metadata Information for Telemetry.");
         try
         {
Example #3
0
        public async Task GatewayStoreClientTimeout()
        {
            using (CosmosClient client = TestCommon.CreateCosmosClient(useGateway: true))
            {
                // Creates the store clients in the document client
                await client.DocumentClient.EnsureValidClientAsync();

                // Get the GatewayStoreModel
                GatewayStoreModel gatewayStore;
                using (DocumentServiceRequest serviceRequest = new DocumentServiceRequest(
                           operationType: OperationType.Read,
                           resourceIdOrFullName: null,
                           resourceType: ResourceType.Database,
                           body: null,
                           headers: null,
                           isNameBased: false,
                           authorizationTokenType: AuthorizationTokenType.PrimaryMasterKey))
                {
                    serviceRequest.UseGatewayMode = true;
                    gatewayStore = (GatewayStoreModel)client.DocumentClient.GetStoreProxy(serviceRequest);
                }

                DocumentClient   documentClient           = client.DocumentClient;
                FieldInfo        cosmosHttpClientProperty = client.DocumentClient.GetType().GetField("httpClient", BindingFlags.NonPublic | BindingFlags.Instance);
                CosmosHttpClient cosmosHttpClient         = (CosmosHttpClient)cosmosHttpClientProperty.GetValue(documentClient);

                // Set the http request timeout to 10 ms to cause a timeout exception
                HttpClient httpClient         = new HttpClient(new TimeOutHttpClientHandler());
                FieldInfo  httpClientProperty = cosmosHttpClient.GetType().GetField("httpClient", BindingFlags.NonPublic | BindingFlags.Instance);
                httpClientProperty.SetValue(cosmosHttpClient, httpClient);

                FieldInfo gatewayRequestTimeoutProperty = cosmosHttpClient.GetType().GetField("GatewayRequestTimeout", BindingFlags.NonPublic | BindingFlags.Static);
                gatewayRequestTimeoutProperty.SetValue(cosmosHttpClient, TimeSpan.FromSeconds(1));

                // Verify the failure has the required info
                try
                {
                    await client.CreateDatabaseAsync("TestGatewayTimeoutDb" + Guid.NewGuid().ToString());

                    Assert.Fail("Operation should have timed out:");
                }
                catch (CosmosException rte)
                {
                    string message = rte.ToString();
                    Assert.IsTrue(message.Contains("Start Time"), "Start Time:" + message);
                    Assert.IsTrue(message.Contains("Total Duration"), "Total Duration:" + message);
                    Assert.IsTrue(message.Contains("Http Client Timeout"), "Http Client Timeout:" + message);
                    Assert.IsTrue(message.Contains("Activity id"), "Activity id:" + message);
                }
            }
        }
Example #4
0
        public async Task HttpClientConnectionLimitTest()
        {
            int gatewayConnectionLimit = 1;

            IReadOnlyList <string> excludeConnections = GetActiveConnections();
            CosmosClient           cosmosClient       = new CosmosClient(
                ConfigurationManager.AppSettings["GatewayEndpoint"],
                ConfigurationManager.AppSettings["MasterKey"],
                new CosmosClientOptions
            {
                ApplicationName = "test",
                GatewayModeMaxConnectionLimit = gatewayConnectionLimit,
                ConnectionMode     = ConnectionMode.Gateway,
                ConnectionProtocol = Protocol.Https
            }
                );

            FieldInfo         httpClient        = cosmosClient.DocumentClient.GetType().GetField("httpClient", BindingFlags.NonPublic | BindingFlags.Instance);
            CosmosHttpClient  cosmosHttpClient  = (CosmosHttpClient)httpClient.GetValue(cosmosClient.DocumentClient);
            HttpClientHandler httpClientHandler = (HttpClientHandler)cosmosHttpClient.HttpMessageHandler;

            Assert.AreEqual(gatewayConnectionLimit, httpClientHandler.MaxConnectionsPerServer);

            Cosmos.Database database = await cosmosClient.CreateDatabaseAsync(Guid.NewGuid().ToString());

            Container container = await database.CreateContainerAsync(
                "TestConnections",
                "/pk",
                throughput : 20000);

            List <Task> creates = new List <Task>();

            for (int i = 0; i < 100; i++)
            {
                creates.Add(container.CreateItemAsync <dynamic>(new { id = Guid.NewGuid().ToString(), pk = Guid.NewGuid().ToString() }));
            }

            await Task.WhenAll(creates);

            // Verify the handler still exists after client warm up
            //Assert.AreEqual(gatewayConnectionLimit, httpClientHandler.MaxConnectionsPerServer);
            IReadOnlyList <string> afterConnections = GetActiveConnections();

            // Clean up the database and container
            await database.DeleteAsync();

            int connectionDiff = afterConnections.Count - excludeConnections.Count;

            Assert.IsTrue(connectionDiff <= gatewayConnectionLimit, $"Connection before : {excludeConnections.Count}, after {afterConnections.Count}");
        }
        public async Task HttpClientConnectionLimitTest()
        {
            int gatewayConnectionLimit = 1;

            IReadOnlyList <string> excludeConnections = GetActiveConnections();

            using (CosmosClient cosmosClient = new CosmosClient(
                       ConfigurationManager.AppSettings["GatewayEndpoint"],
                       ConfigurationManager.AppSettings["MasterKey"],
                       new CosmosClientOptions
            {
                ApplicationName = "test",
                GatewayModeMaxConnectionLimit = gatewayConnectionLimit,
                ConnectionMode = ConnectionMode.Gateway,
                ConnectionProtocol = Protocol.Https
            }
                       ))
            {
                CosmosHttpClient  cosmosHttpClient  = cosmosClient.DocumentClient.httpClient;
                HttpClientHandler httpClientHandler = (HttpClientHandler)cosmosHttpClient.HttpMessageHandler;
                Assert.AreEqual(gatewayConnectionLimit, httpClientHandler.MaxConnectionsPerServer);

                Cosmos.Database database = await cosmosClient.CreateDatabaseAsync(Guid.NewGuid().ToString());

                Container container = await database.CreateContainerAsync(
                    "TestConnections",
                    "/pk",
                    throughput : 20000);

                List <Task> creates = new List <Task>();
                for (int i = 0; i < 100; i++)
                {
                    creates.Add(container.CreateItemAsync <dynamic>(new { id = Guid.NewGuid().ToString(), pk = Guid.NewGuid().ToString() }));
                }

                await Task.WhenAll(creates);

                // Clean up the database and container
                await database.DeleteAsync();
            }


            IReadOnlyList <string> afterConnections = GetActiveConnections();

            int connectionDiff = afterConnections.Count - excludeConnections.Count;

            Assert.IsTrue(connectionDiff <= gatewayConnectionLimit, $"Connection before : {excludeConnections.Count}, after {afterConnections.Count};" +
                          $"Before connections: {JsonConvert.SerializeObject(excludeConnections)}; After connections: {JsonConvert.SerializeObject(afterConnections)}");
        }
        public void VerifyHttpClientHandlerIsSet()
        {
            string endpoint = AccountEndpoint;
            string key      = "425Mcv8CXQqzRNCgFNjIhT424GK99CKJvASowTnq15Vt8LeahXTcN5wt3342vQ==";

            IWebProxy webProxy = new TestWebProxy();

            CosmosClientBuilder cosmosClientBuilder = new CosmosClientBuilder(
                accountEndpoint: endpoint,
                authKeyOrResourceToken: key);

            cosmosClientBuilder.WithConnectionModeGateway(
                maxConnectionLimit: null,
                webProxy: webProxy);

            CosmosClient      cosmosClient     = cosmosClientBuilder.Build();
            CosmosHttpClient  cosmosHttpClient = cosmosClient.DocumentClient.httpClient;
            HttpClientHandler handler          = (HttpClientHandler)cosmosHttpClient.HttpMessageHandler;

            Assert.IsTrue(object.ReferenceEquals(webProxy, handler.Proxy));
        }
        public GlobalAddressResolver(
            GlobalEndpointManager endpointManager,
            GlobalPartitionEndpointManager partitionKeyRangeLocationCache,
            Protocol protocol,
            ICosmosAuthorizationTokenProvider tokenProvider,
            CollectionCache collectionCache,
            PartitionKeyRangeCache routingMapProvider,
            IServiceConfigurationReader serviceConfigReader,
            ConnectionPolicy connectionPolicy,
            CosmosHttpClient httpClient)
        {
            this.endpointManager = endpointManager;
            this.partitionKeyRangeLocationCache = partitionKeyRangeLocationCache;
            this.protocol            = protocol;
            this.tokenProvider       = tokenProvider;
            this.collectionCache     = collectionCache;
            this.routingMapProvider  = routingMapProvider;
            this.serviceConfigReader = serviceConfigReader;
            this.httpClient          = httpClient;

            int maxBackupReadEndpoints =
                !connectionPolicy.EnableReadRequestsFallback.HasValue || connectionPolicy.EnableReadRequestsFallback.Value
                ? GlobalAddressResolver.MaxBackupReadRegions : 0;

            this.enableTcpConnectionEndpointRediscovery = connectionPolicy.EnableTcpConnectionEndpointRediscovery;

            this.maxEndpoints = maxBackupReadEndpoints + 2; // for write and alternate write endpoint (during failover)

            this.addressCacheByEndpoint = new ConcurrentDictionary <Uri, EndpointCache>();

            foreach (Uri endpoint in endpointManager.WriteEndpoints)
            {
                this.GetOrAddEndpoint(endpoint);
            }

            foreach (Uri endpoint in endpointManager.ReadEndpoints)
            {
                this.GetOrAddEndpoint(endpoint);
            }
        }
        public async Task ResponseMessageHasRequestMessageAsync()
        {
            // We don't set the RequestMessage property on purpose on the Failed response
            // This will make it go through GatewayStoreClient.CreateDocumentClientExceptionAsync
            Func <HttpRequestMessage, Task <HttpResponseMessage> > sendFunc = request =>
            {
                HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.NotFound)
                {
                    Content = new StringContent("test")
                };
                return(Task.FromResult(response));
            };

            DocumentClientEventSource eventSource      = DocumentClientEventSource.Instance;
            HttpMessageHandler        messageHandler   = new MockMessageHandler(sendFunc);
            CosmosHttpClient          cosmoshttpClient = MockCosmosUtil.CreateCosmosHttpClient(() => new HttpClient(messageHandler));

            HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, new Uri("http://localhost"));

            HttpResponseMessage responseMessage = await cosmoshttpClient.SendHttpAsync(() => new ValueTask <HttpRequestMessage>(httpRequestMessage), ResourceType.Collection, null, default);

            Assert.AreEqual(httpRequestMessage, responseMessage.RequestMessage);
        }