diff --git a/Directory.Build.props b/Directory.Build.props
index 015f0e14cc..c2eb610e0f 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -3,7 +3,7 @@
3.57.0
3.58.0
preview.0
- 3.41.3
+ 3.42.0
1.0.0
beta.0
2.0.5
diff --git a/Microsoft.Azure.Cosmos/src/DocumentClient.cs b/Microsoft.Azure.Cosmos/src/DocumentClient.cs
index f4fbcfca01..293c93abf8 100644
--- a/Microsoft.Azure.Cosmos/src/DocumentClient.cs
+++ b/Microsoft.Azure.Cosmos/src/DocumentClient.cs
@@ -6792,8 +6792,6 @@ private void InitializeDirectConnectivity(IStoreClientFactory storeClientFactory
private void CreateStoreModel(bool subscribeRntbdStatus)
{
- AccountConfigurationProperties accountConfigurationProperties = new (EnableNRegionSynchronousCommit: this.accountServiceConfiguration.AccountProperties.EnableNRegionSynchronousCommit);
-
//EnableReadRequestsFallback, if not explicity set on the connection policy,
//is false if the account's consistency is bounded staleness,
//and true otherwise.
@@ -6808,8 +6806,7 @@ private void CreateStoreModel(bool subscribeRntbdStatus)
this.UseMultipleWriteLocations && (this.accountServiceConfiguration.DefaultConsistencyLevel != Documents.ConsistencyLevel.Strong),
true,
enableReplicaValidation: this.isReplicaAddressValidationEnabled,
- sessionRetryOptions: this.ConnectionPolicy.SessionRetryOptions,
- accountConfigurationProperties: accountConfigurationProperties);
+ sessionRetryOptions: this.ConnectionPolicy.SessionRetryOptions);
if (subscribeRntbdStatus)
{
diff --git a/Microsoft.Azure.Cosmos/src/Resource/Settings/CosmosAccountServiceConfiguration.cs b/Microsoft.Azure.Cosmos/src/Resource/Settings/CosmosAccountServiceConfiguration.cs
index 24aad85156..6baa478ecd 100644
--- a/Microsoft.Azure.Cosmos/src/Resource/Settings/CosmosAccountServiceConfiguration.cs
+++ b/Microsoft.Azure.Cosmos/src/Resource/Settings/CosmosAccountServiceConfiguration.cs
@@ -9,7 +9,7 @@ namespace Microsoft.Azure.Cosmos
using System.Threading.Tasks;
using Microsoft.Azure.Documents;
- internal class CosmosAccountServiceConfiguration : IServiceConfigurationReader
+ internal class CosmosAccountServiceConfiguration : IServiceConfigurationReaderVnext
{
private Func> accountPropertiesTaskFunc { get; }
@@ -53,6 +53,8 @@ public CosmosAccountServiceConfiguration(Func> accountPr
public string SubscriptionId => throw new NotImplementedException();
+ public bool EnableNRegionSynchronousCommit => this.AccountProperties.EnableNRegionSynchronousCommit;
+
public async Task InitializeAsync()
{
if (this.AccountProperties == null)
diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientCreateAndInitializeTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientCreateAndInitializeTest.cs
index 1813700e05..1444542f9f 100644
--- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientCreateAndInitializeTest.cs
+++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientCreateAndInitializeTest.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
+ using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
@@ -364,5 +365,105 @@ public async Task CreateAndInitializeAsync_WithValidDatabaseAndInvalidContainer_
Assert.IsNotNull(ce);
Assert.AreEqual(HttpStatusCode.NotFound, ce.StatusCode);
}
+
+ ///
+ /// Test to validate write item operations with transport interceptor that modifies
+ /// GlobalNRegionCommittedGLSN header and HTTP interceptor that sets EnableNRegionSynchronousCommit
+ /// in AccountProperties response.
+ ///
+ [TestMethod]
+ [Owner("aavasthy")]
+ public async Task CreateAndInitializeAsync_WriteItemOperationWithNRegionCommitTest()
+ {
+ // Custom GlobalNRegionCommittedGLSN value to inject
+ const long customGlobalNRegionCommittedGLSN = 100;
+
+ // HTTP handler to intercept AccountProperties response and set EnableNRegionSynchronousCommit = true
+ HttpClientHandlerHelper httpClientHandlerHelper = new HttpClientHandlerHelper
+ {
+ ResponseIntercepter = async (response, request) =>
+ {
+ if (request.RequestUri.AbsolutePath.EndsWith("/", StringComparison.OrdinalIgnoreCase) ||
+ request.RequestUri.AbsolutePath.Equals(string.Empty))
+ {
+ if (response.IsSuccessStatusCode)
+ {
+ string content = await response.Content.ReadAsStringAsync();
+ Newtonsoft.Json.Linq.JObject accountJson = Newtonsoft.Json.Linq.JObject.Parse(content);
+
+ accountJson[Constants.Properties.EnableNRegionSynchronousCommit] = true;
+
+ string modifiedContent = accountJson.ToString();
+ response.Content = new StringContent(modifiedContent, System.Text.Encoding.UTF8, "application/json");
+ }
+ }
+ return response;
+ }
+ };
+
+ await this.TestInit(
+ customizeClientBuilder: (builder) =>
+ {
+ builder.WithConnectionModeDirect();
+ builder.WithHttpClientFactory(() => new HttpClient(httpClientHandlerHelper));
+ builder.WithTransportClientHandlerFactory(transportClient =>
+ new TransportClientHelper.TransportClientWrapper(
+ client: transportClient,
+ interceptorAfterResult: (request, storeResponse) =>
+ {
+ // Override GlobalNRegionCommittedGLSN header in the response for Document operations
+ if (request.ResourceType == ResourceType.Document)
+ {
+ storeResponse.Headers.Set(
+ WFConstants.BackendHeaders.GlobalNRegionCommittedGLSN,
+ customGlobalNRegionCommittedGLSN.ToString(CultureInfo.InvariantCulture));
+ }
+ return storeResponse;
+ }));
+ });
+
+ string containerName = "NRegionCommitTestContainer_" + Guid.NewGuid().ToString("N");
+ ContainerResponse containerResponse = await this.database.CreateContainerAsync(
+ new ContainerProperties(id: containerName, partitionKeyPath: PartitionKey),
+ cancellationToken: this.cancellationToken);
+ Assert.IsNotNull(containerResponse);
+
+ Container container = containerResponse.Container;
+
+ try
+ {
+ for (int i = 0; i < 2; i++)
+ {
+ ToDoActivity item = new()
+ {
+ id = Guid.NewGuid().ToString(),
+ pk = "testPartition",
+ description = $"Test item {i}",
+ };
+
+ // Act
+ ItemResponse writeResponse = await container.CreateItemAsync(
+ item: item,
+ partitionKey: new Cosmos.PartitionKey(item.pk));
+
+ // Assert
+ Assert.AreEqual(HttpStatusCode.Created, writeResponse.StatusCode);
+
+ // Assert: Verify GlobalNRegionCommittedGLSN is present in diagnostics with value 100
+ string diagnostics = writeResponse.Diagnostics.ToString();
+
+ Assert.IsTrue(
+ diagnostics.Contains($"\"GlobalNRegionCommittedGLSN\":{customGlobalNRegionCommittedGLSN}") ||
+ diagnostics.Contains($"\"GlobalNRegionCommittedGLSN\": {customGlobalNRegionCommittedGLSN}"),
+ $"Expected GlobalNRegionCommittedGLSN to be {customGlobalNRegionCommittedGLSN} in diagnostics. Actual diagnostics: {diagnostics}");
+
+ }
+ }
+ finally
+ {
+ // Cleanup: Delete the test container
+ await container.DeleteContainerAsync();
+ }
+ }
}
}
diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/DocumentClientUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/DocumentClientUnitTests.cs
index 34a35ccd46..c73d033d61 100644
--- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/DocumentClientUnitTests.cs
+++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/DocumentClientUnitTests.cs
@@ -276,113 +276,6 @@ private void TestRetryOnThrottled(int? numberOfRetries)
Assert.IsTrue(throttled);
}
- [TestMethod]
- [DataRow(false, DisplayName = "NRegion Synchronous commit is disabled for the account")]
- [DataRow(true, DisplayName = "NRegion Synchronous commit is enabled for the account")]
- public void EnableNRegionSynchronousCommit_PassedToStoreClient(bool nRegionCommitEnabled)
- {
-
- StoreClient storeClient = new StoreClient(
- new Mock().Object,
- new SessionContainer(string.Empty),
- new Mock().Object,
- new Mock().Object,
- Protocol.Tcp,
- new Mock().Object);
- // Arrange
- Mock mockStoreClientFactory = new Mock();
- mockStoreClientFactory.Setup(f => f.CreateStoreClient(
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny()
- )).Returns(storeClient);
-
- DocumentClient documentClient = new DocumentClient(
- new Uri("https://localhost:8081"),
- new Mock().Object,
- new EventHandler((s, e) => { }),
- new ConnectionPolicy(),
- null, // desiredConsistencyLevel
- null, // serializerSettings
- ApiType.None,
- new EventHandler((s, e) => { }),
- null, // handler
- new Mock().Object,
- null, // enableCpuMonitor
- new Func(tc => tc),
- mockStoreClientFactory.Object,
- false, // isLocalQuorumConsistency
- "testClientId",
- new RemoteCertificateValidationCallback((sender, certificate, chain, sslPolicyErrors) => true),
- new Mock().Object,
- new Mock().Object,
- true // enableAsyncCacheExceptionNoSharing
- );
-
- AccountProperties accountProperties = new AccountProperties
- {
- // Set the property to true for test
- EnableNRegionSynchronousCommit = nRegionCommitEnabled,
- };
-
- AccountConsistency ac = new AccountConsistency();
- ac.DefaultConsistencyLevel = (Cosmos.ConsistencyLevel) ConsistencyLevel.Session;
- accountProperties.Consistency = ac;
-
- Func> getDatabaseAccountFn = () =>
- // When called with any Uri, return the expected AccountProperties
- Task.FromResult(accountProperties);
-
- CosmosAccountServiceConfiguration accountServiceConfiguration = new CosmosAccountServiceConfiguration(
- getDatabaseAccountFn);
-
- typeof(CosmosAccountServiceConfiguration)
- .GetProperty("AccountProperties", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)
- .SetValue(accountServiceConfiguration, accountProperties);
-
- //Inject the accountServiceConfiguration into the DocumentClient via reflection.
- typeof(DocumentClient)
- .GetProperty("accountServiceConfiguration", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)
- .SetValue(documentClient, accountServiceConfiguration);
-
-
- typeof(DocumentClient)
- .GetField("storeClientFactory", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)
- .SetValue(documentClient, mockStoreClientFactory.Object);
-
- // Act: Call the private method via reflection
- typeof(DocumentClient)
- .GetMethod("CreateStoreModel", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)
- .Invoke(documentClient, new object[] { true });
-
- // Assert: Verify the correct value was passed
- mockStoreClientFactory.Verify(f =>
- f.CreateStoreClient(
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.Is(config => config.EnableNRegionSynchronousCommit == accountProperties.EnableNRegionSynchronousCommit),
- It.IsAny()),
- Times.Once,
- "EnableNRegionSynchronousCommit was not passed correctly to AccountConfigurationProperties and StoreClient.");
- }
-
private DocumentClientException CreateTooManyRequestException(int retryAfterInMilliseconds)
{
HttpResponseMessage responseMessage = new HttpResponseMessage();
diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientRetryPolicyTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientRetryPolicyTests.cs
index 01beceec22..b595711070 100644
--- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientRetryPolicyTests.cs
+++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientRetryPolicyTests.cs
@@ -568,8 +568,7 @@ private async Task ValidateConnectTimeoutTriggersClientRetryPolicyAsync(
useMultipleWriteLocations: useMultipleWriteLocations,
detectClientConnectivityIssues: true,
disableRetryWithRetryPolicy: false,
- enableReplicaValidation: false,
- accountConfigurationProperties: null);
+ enableReplicaValidation: false);
// Reducing retry timeout to avoid long-running tests
replicatedResourceClient.GoneAndRetryWithRetryTimeoutInSecondsOverride = 1;
diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/StoreReaderTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/StoreReaderTest.cs
index 8f5521c2a2..a8c5c75087 100644
--- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/StoreReaderTest.cs
+++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/StoreReaderTest.cs
@@ -600,13 +600,13 @@ public void GlobalStrongConsistentWriteMockTest()
{
TransportClient mockTransportClient = this.GetMockTransportClientForGlobalStrongWrites(addressInformation, i, false, false, false);
StoreReader storeReader = new StoreReader(mockTransportClient, addressSelector, new AddressEnumerator(), sessionContainer, false);
- ConsistencyWriter consistencyWriter = new ConsistencyWriter(addressSelector, sessionContainer, mockTransportClient, mockServiceConfigReader.Object, mockAuthorizationTokenProvider.Object, false, false, accountConfigurationProperties: null);
+ ConsistencyWriter consistencyWriter = new ConsistencyWriter(addressSelector, sessionContainer, mockTransportClient, mockServiceConfigReader.Object, mockAuthorizationTokenProvider.Object, false, false);
StoreResponse response = consistencyWriter.WriteAsync(entity, new TimeoutHelper(TimeSpan.FromSeconds(30)), false).Result;
Assert.AreEqual(100, response.LSN);
//globalCommittedLsn never catches up in this case
mockTransportClient = this.GetMockTransportClientForGlobalStrongWrites(addressInformation, i, true, false, false);
- consistencyWriter = new ConsistencyWriter(addressSelector, sessionContainer, mockTransportClient, mockServiceConfigReader.Object, mockAuthorizationTokenProvider.Object, false, false, accountConfigurationProperties: null);
+ consistencyWriter = new ConsistencyWriter(addressSelector, sessionContainer, mockTransportClient, mockServiceConfigReader.Object, mockAuthorizationTokenProvider.Object, false, false);
try
{
response = consistencyWriter.WriteAsync(entity, new TimeoutHelper(TimeSpan.FromSeconds(30)), false).Result;
@@ -617,17 +617,17 @@ public void GlobalStrongConsistentWriteMockTest()
}
mockTransportClient = this.GetMockTransportClientForGlobalStrongWrites(addressInformation, i, false, true, false);
- consistencyWriter = new ConsistencyWriter(addressSelector, sessionContainer, mockTransportClient, mockServiceConfigReader.Object, mockAuthorizationTokenProvider.Object, false, false, accountConfigurationProperties: null);
+ consistencyWriter = new ConsistencyWriter(addressSelector, sessionContainer, mockTransportClient, mockServiceConfigReader.Object, mockAuthorizationTokenProvider.Object, false, false);
response = consistencyWriter.WriteAsync(entity, new TimeoutHelper(TimeSpan.FromSeconds(30)), false).Result;
Assert.AreEqual(100, response.LSN);
mockTransportClient = this.GetMockTransportClientForGlobalStrongWrites(addressInformation, i, false, true, true);
- consistencyWriter = new ConsistencyWriter(addressSelector, sessionContainer, mockTransportClient, mockServiceConfigReader.Object, mockAuthorizationTokenProvider.Object, false, false, accountConfigurationProperties: null);
+ consistencyWriter = new ConsistencyWriter(addressSelector, sessionContainer, mockTransportClient, mockServiceConfigReader.Object, mockAuthorizationTokenProvider.Object, false, false);
response = consistencyWriter.WriteAsync(entity, new TimeoutHelper(TimeSpan.FromSeconds(30)), false).Result;
Assert.AreEqual(100, response.LSN);
mockTransportClient = this.GetMockTransportClientForGlobalStrongWrites(addressInformation, i, false, false, true);
- consistencyWriter = new ConsistencyWriter(addressSelector, sessionContainer, mockTransportClient, mockServiceConfigReader.Object, mockAuthorizationTokenProvider.Object, false, false, accountConfigurationProperties: null);
+ consistencyWriter = new ConsistencyWriter(addressSelector, sessionContainer, mockTransportClient, mockServiceConfigReader.Object, mockAuthorizationTokenProvider.Object, false, false);
response = consistencyWriter.WriteAsync(entity, new TimeoutHelper(TimeSpan.FromSeconds(30)), false).Result;
Assert.AreEqual(100, response.LSN);
}
@@ -960,8 +960,9 @@ public void TestWhenNRegionSynchronousCommitEnabledThenDoBarrierHead()
ISessionContainer sessionContainer = new SessionContainer(string.Empty);
- Mock mockServiceConfigReader = new Mock();
+ Mock mockServiceConfigReader = new Mock();
mockServiceConfigReader.Setup(reader => reader.DefaultConsistencyLevel).Returns(Documents.ConsistencyLevel.Session);
+ mockServiceConfigReader.Setup(reader => reader.EnableNRegionSynchronousCommit).Returns(true);
Mock mockAuthorizationTokenProvider = new Mock();
mockAuthorizationTokenProvider.Setup(provider => provider.AddSystemAuthorizationHeaderAsync(
@@ -971,9 +972,8 @@ public void TestWhenNRegionSynchronousCommitEnabledThenDoBarrierHead()
TransportClient mockTransportClient = this.GetMockTransportClientForNRegionSynchronousWrites(addressInformation, false);
StoreReader storeReader = new StoreReader(mockTransportClient, addressSelector, new AddressEnumerator(), sessionContainer, false);
- AccountConfigurationProperties accountConfigurationProperties = new AccountConfigurationProperties(true);
- ConsistencyWriter consistencyWriter = new ConsistencyWriter(addressSelector, sessionContainer, mockTransportClient, mockServiceConfigReader.Object, mockAuthorizationTokenProvider.Object, false, false, accountConfigurationProperties: accountConfigurationProperties);
+ ConsistencyWriter consistencyWriter = new ConsistencyWriter(addressSelector, sessionContainer, mockTransportClient, mockServiceConfigReader.Object, mockAuthorizationTokenProvider.Object, false, false);
StoreResponse response = consistencyWriter.WriteAsync(entity, new TimeoutHelper(TimeSpan.FromSeconds(3000)), false).Result;
Assert.AreEqual(100, response.LSN);
@@ -983,7 +983,7 @@ public void TestWhenNRegionSynchronousCommitEnabledThenDoBarrierHead()
mockTransportClient = this.GetMockTransportClientForNRegionSynchronousWrites(addressInformation, true);
storeReader = new StoreReader(mockTransportClient, addressSelector, new AddressEnumerator(), sessionContainer, false);
- consistencyWriter = new ConsistencyWriter(addressSelector, sessionContainer, mockTransportClient, mockServiceConfigReader.Object, mockAuthorizationTokenProvider.Object, false, false, accountConfigurationProperties: accountConfigurationProperties);
+ consistencyWriter = new ConsistencyWriter(addressSelector, sessionContainer, mockTransportClient, mockServiceConfigReader.Object, mockAuthorizationTokenProvider.Object, false, false);
response = consistencyWriter.WriteAsync(entity, new TimeoutHelper(TimeSpan.FromSeconds(3000)), false).Result;
Assert.Fail();
}