diff --git a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs index 7b6b7db939..97ad2cd468 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs @@ -350,6 +350,20 @@ public CosmosSerializer Serializer } } + /// + /// Limits the operations to the provided endpoint on the CosmosClient. + /// + /// + /// Default value is false. + /// + /// + /// When the value of this property is false, the SDK will automatically discover write and read regions, and use them when the configured application region is not available. + /// When set to true, availability is limited to the endpoint specified on the CosmosClient constructor. + /// Defining the is not allowed when setting the value to true. + /// + /// + public bool LimitToEndpoint { get; set; } = false; + /// /// Allows optimistic batching of requests to service. Setting this option might impact the latency of the operations. Hence this option is recommended for non-latency sensitive scenarios only. /// @@ -499,6 +513,7 @@ internal CosmosClientOptions Clone() internal ConnectionPolicy GetConnectionPolicy() { this.ValidateDirectTCPSettings(); + this.ValidateLimitToEndpointSettings(); ConnectionPolicy connectionPolicy = new ConnectionPolicy() { MaxConnectionLimit = this.GatewayModeMaxConnectionLimit, @@ -510,7 +525,8 @@ internal ConnectionPolicy GetConnectionPolicy() IdleTcpConnectionTimeout = this.IdleTcpConnectionTimeout, OpenTcpConnectionTimeout = this.OpenTcpConnectionTimeout, MaxRequestsPerTcpConnection = this.MaxRequestsPerTcpConnection, - MaxTcpConnectionsPerEndpoint = this.MaxTcpConnectionsPerEndpoint + MaxTcpConnectionsPerEndpoint = this.MaxTcpConnectionsPerEndpoint, + EnableEndpointDiscovery = !this.LimitToEndpoint }; if (this.ApplicationRegion != null) @@ -609,6 +625,14 @@ private static string GetValueFromConnectionString(string connectionString, stri throw new ArgumentException("The connection string is missing a required property: " + keyName); } + private void ValidateLimitToEndpointSettings() + { + if (!string.IsNullOrEmpty(this.ApplicationRegion) && this.LimitToEndpoint) + { + throw new ArgumentException($"Cannot specify {nameof(this.ApplicationRegion)} and enable {nameof(this.LimitToEndpoint)}. Only one can be set."); + } + } + private void ValidateDirectTCPSettings() { string settingName = string.Empty; @@ -666,6 +690,12 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s { writer.WriteValue(cosmosJsonSerializerWrapper.InternalJsonSerializer.GetType().ToString()); } + + CosmosSerializer cosmosSerializer = value as CosmosSerializer; + if (cosmosSerializer is CosmosSerializer) + { + writer.WriteValue(cosmosSerializer.GetType().ToString()); + } } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) diff --git a/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs b/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs index 7c8a00e852..cc62274283 100644 --- a/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs +++ b/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs @@ -145,6 +145,36 @@ public CosmosClientBuilder WithApplicationRegion(string applicationRegion) return this; } + /// + /// Limits the operations to the provided endpoint on the CosmosClientBuilder constructor. + /// + /// Whether operations are limited to the endpoint or not. + /// Default value is false. + /// + /// When the value of is false, the SDK will automatically discover all account write and read regions, and use them when the configured application region is not available. + /// When set to true, availability is limited to the endpoint specified on the CosmosClientBuilder constructor. + /// Using is not allowed when the value is true. + /// + /// The example below creates a new to limit the endpoint to East US. + /// + /// + /// + /// + /// The current . + /// + /// + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint) + { + this.clientOptions.LimitToEndpoint = limitToEndpoint; + return this; + } + /// /// Sets the request timeout in seconds when connecting to the Azure Cosmos DB service. /// diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs index e2b68dd4a0..bba3500e20 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs @@ -68,6 +68,7 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() Assert.IsNull(clientOptions.SerializerOptions); Assert.IsNull(clientOptions.Serializer); Assert.IsNull(clientOptions.WebProxy); + Assert.IsFalse(clientOptions.LimitToEndpoint); //Verify GetConnectionPolicy returns the correct values for default ConnectionPolicy policy = clientOptions.GetConnectionPolicy(); @@ -79,6 +80,7 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() Assert.IsNull(policy.OpenTcpConnectionTimeout); Assert.IsNull(policy.MaxRequestsPerTcpConnection); Assert.IsNull(policy.MaxTcpConnectionsPerEndpoint); + Assert.IsTrue(policy.EnableEndpointDiscovery); cosmosClientBuilder.WithApplicationRegion(region) .WithConnectionModeGateway(maxConnections, webProxy) @@ -372,6 +374,37 @@ public void VerifyCorrectProtocolIsSet() Assert.AreEqual(Protocol.Tcp, cosmosClientOptions.ConnectionProtocol); } + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void VerifyLimitToEndpointSettings() + { + CosmosClientOptions cosmosClientOptions = new CosmosClientOptions { ApplicationRegion = LocationNames.EastUS, LimitToEndpoint = true }; + cosmosClientOptions.GetConnectionPolicy(); + } + + [TestMethod] + public void WithLimitToEndpointAffectsEndpointDiscovery() + { + CosmosClientBuilder cosmosClientBuilder = new CosmosClientBuilder( + accountEndpoint: AccountEndpoint, + authKeyOrResourceToken: Guid.NewGuid().ToString()); + + CosmosClientOptions cosmosClientOptions = cosmosClientBuilder.Build(new MockDocumentClient()).ClientOptions; + Assert.IsFalse(cosmosClientOptions.LimitToEndpoint); + + ConnectionPolicy connectionPolicy = cosmosClientOptions.GetConnectionPolicy(); + Assert.IsTrue(connectionPolicy.EnableEndpointDiscovery); + + cosmosClientBuilder + .WithLimitToEndpoint(true); + + cosmosClientOptions = cosmosClientBuilder.Build(new MockDocumentClient()).ClientOptions; + Assert.IsTrue(cosmosClientOptions.LimitToEndpoint); + + connectionPolicy = cosmosClientOptions.GetConnectionPolicy(); + Assert.IsFalse(connectionPolicy.EnableEndpointDiscovery); + } + private class TestWebProxy : IWebProxy { public ICredentials Credentials { get; set; } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/DotNetSDKAPI.json index 1e587f8600..c64c3b0a9c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/DotNetSDKAPI.json @@ -1237,6 +1237,18 @@ "CosmosClientOptions": { "Subclasses": {}, "Members": { + "Boolean get_LimitToEndpoint()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Boolean get_LimitToEndpoint()" + }, + "Boolean LimitToEndpoint": { + "Type": "Property", + "Attributes": [], + "MethodInfo": null + }, "Int32 GatewayModeMaxConnectionLimit": { "Type": "Property", "Attributes": [], @@ -1454,6 +1466,13 @@ "Attributes": [], "MethodInfo": "Void set_IdleTcpConnectionTimeout(System.Nullable`1[System.TimeSpan])" }, + "Void set_LimitToEndpoint(Boolean)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_LimitToEndpoint(Boolean)" + }, "Void set_MaxRequestsPerTcpConnection(System.Nullable`1[System.Int32])": { "Type": "Method", "Attributes": [], @@ -2367,6 +2386,11 @@ "Attributes": [], "MethodInfo": "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithCustomSerializer(Microsoft.Azure.Cosmos.CosmosSerializer)" }, + "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithLimitToEndpoint(Boolean)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithLimitToEndpoint(Boolean)" + }, "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithRequestTimeout(System.TimeSpan)": { "Type": "Method", "Attributes": [], diff --git a/changelog.md b/changelog.md index da00a4695b..3b709ee3a7 100644 --- a/changelog.md +++ b/changelog.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- [#814](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/814) Ability to limit to configured endpoint only - [#822](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/822) GROUP BY query support. ## [3.2.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.2.0) - 2019-09-17