Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
010de6c
Fix null contacted region name on multimaster default endpoint fallback
NaluTripician Feb 18, 2026
0398d02
Merge branch 'master' into users/nalutripician/issue-5095-contacted-r…
NaluTripician Feb 23, 2026
ae0ff9e
Merge branch 'master' into users/nalutripician/issue-5095-contacted-r…
NaluTripician Feb 24, 2026
5c07966
Merge branch 'master' into users/nalutripician/issue-5095-contacted-r…
NaluTripician Feb 24, 2026
1423cde
Merge branch 'master' into users/nalutripician/issue-5095-contacted-r…
NaluTripician Apr 7, 2026
04a90a3
Merge branch 'master' into users/nalutripician/issue-5095-contacted-r…
NaluTripician Apr 8, 2026
7e5cfe5
Diagnostics: Fixes review comments on multimaster default endpoint re…
NaluTripician Apr 8, 2026
cd357e3
Diagnostics: Adds clarifying comment and edge case tests for multimas…
NaluTripician Apr 9, 2026
0b38a94
Merge branch 'master' into users/nalutripician/issue-5095-contacted-r…
NaluTripician Apr 14, 2026
f626482
Merge branch 'master' into users/nalutripician/issue-5095-contacted-r…
NaluTripician Apr 15, 2026
d63f4d4
Address review feedback: use Any(), collapse if, remove whitespace noise
NaluTripician Apr 15, 2026
008f9a0
Merge branch 'master' into users/nalutripician/issue-5095-contacted-r…
NaluTripician Apr 16, 2026
04e03eb
Address Kiran's review feedback
NaluTripician Apr 16, 2026
c724082
Merge branch 'master' into users/nalutripician/issue-5095-contacted-r…
NaluTripician Apr 21, 2026
b2ea3f0
Merge branch 'master' into users/nalutripician/issue-5095-contacted-r…
NaluTripician Apr 21, 2026
adbb741
Fix TryGetLocationForGatewayDiagnostics returning true for unknown en…
NaluTripician Apr 21, 2026
dbf081c
Merge branch 'master' into users/nalutripician/issue-5095-contacted-r…
NaluTripician Apr 23, 2026
15666a2
Merge branch 'master' into users/nalutripician/issue-5095-contacted-r…
NaluTripician Apr 28, 2026
591c926
Routing: Refactors GetLocation XML doc to reflect post-PR behavior
NaluTripician Apr 29, 2026
8787eb0
Merge branch 'master' into users/nalutripician/issue-5095-contacted-r…
NaluTripician Apr 30, 2026
340e0f2
Merge branch 'main' into users/nalutripician/issue-5095-contacted-reg…
NaluTripician Apr 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 22 additions & 16 deletions Microsoft.Azure.Cosmos/src/Routing/LocationCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,32 +164,33 @@ public ReadOnlyCollection<Uri> ThinClientWriteEndpoints
public ReadOnlyCollection<string> EffectivePreferredLocations => this.locationInfo.EffectivePreferredLocations;

/// <summary>
/// Returns the location corresponding to the endpoint if location specific endpoint is provided.
/// For the defaultEndPoint, we will return the first available write location.
/// Returns null, in other cases.
/// Returns the region name corresponding to the given endpoint.
/// - If the endpoint matches a known write or read regional endpoint, returns that region name.
/// - If the endpoint is the account's default (global) endpoint and at least one write
/// location is known, returns the first entry of the available write locations list.
/// This applies to both single-master and multi-master accounts. Note that for multi-master
/// accounts the first write location is simply the first region in the configured list,
/// not necessarily the hub/primary write region.
/// - Otherwise, returns null.
/// </summary>
/// <remarks>
/// Today we return null for defaultEndPoint if multiple write locations can be used.
/// This needs to be modifed to figure out proper location in such case.
/// </remarks>
public string GetLocation(Uri endpoint)
{
string location = this.locationInfo.AvailableWriteEndpointByLocation.FirstOrDefault(uri => uri.Value == endpoint).Key ?? this.locationInfo.AvailableReadEndpointByLocation.FirstOrDefault(uri => uri.Value == endpoint).Key;

if (location == null && endpoint == this.defaultEndpoint && !this.CanUseMultipleWriteLocations())
Comment thread
NaluTripician marked this conversation as resolved.
if (location == null
&& endpoint == this.defaultEndpoint
&& this.locationInfo.AvailableWriteLocations.Count > 0)
{
if (this.locationInfo.AvailableWriteEndpointByLocation.Any())
Comment thread
NaluTripician marked this conversation as resolved.
{
return this.locationInfo.AvailableWriteEndpointByLocation.First().Key;
Comment thread
NaluTripician marked this conversation as resolved.
}
return this.locationInfo.AvailableWriteLocations[0];
}

return location;
}

/// <summary>
/// Set region name for a location if present in the locationcache otherwise set region name as null.
/// If endpoint's hostname is same as default endpoint hostname, set regionName as null.
/// For multi-master accounts, if endpoint's hostname is same as default endpoint hostname,
/// set regionName to the first available write region.
/// </summary>
/// <param name="endpoint"></param>
/// <param name="regionName"></param>
Expand All @@ -203,12 +204,17 @@ public bool TryGetLocationForGatewayDiagnostics(Uri endpoint, out string regionN
UriFormat.SafeUnescaped,
StringComparison.OrdinalIgnoreCase) == 0)
{
regionName = null;
return false;
// Use account-level enableMultipleWriteLocations (not CanUseMultipleWriteLocations which also
// requires client opt-in) because diagnostics should resolve the region regardless of whether
// the client uses multi-write. The default endpoint routes to the first write region server-side.
regionName = this.enableMultipleWriteLocations
? this.GetLocation(this.defaultEndpoint)
: null;
return regionName != null;
}

regionName = this.GetLocation(endpoint);
return true;
return regionName != null;
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,95 @@ public void ValidateTryGetLocationForGatewayDiagnostics()
}
}

[TestMethod]
[Owner("ntripician")]
public void ValidateTryGetLocationForGatewayDiagnosticsOnDefaultEndpointForMultiMaster()
{
using GlobalEndpointManager endpointManager = this.Initialize(
useMultipleWriteLocations: true,
enableEndpointDiscovery: true,
isPreferredLocationsListEmpty: false);

string expectedRegionName = this.databaseAccount.WriteLocationsInternal.First().Name;

Assert.AreEqual(expectedRegionName, this.cache.GetLocation(LocationCacheTests.DefaultEndpoint));

Assert.AreEqual(true, this.cache.TryGetLocationForGatewayDiagnostics(LocationCacheTests.DefaultEndpoint, out string regionName));
Assert.AreEqual(expectedRegionName, regionName);

Assert.AreEqual(true, this.cache.TryGetLocationForGatewayDiagnostics(new Uri(LocationCacheTests.DefaultEndpoint, "random/path"), out regionName));
Assert.AreEqual(expectedRegionName, regionName);
}

[TestMethod]
[Owner("ntripician")]
public void ValidateTryGetLocationForGatewayDiagnosticsOnDefaultEndpointForMultiMasterWithClientOptOut()
{
// Account is multi-master but client has UseMultipleWriteLocations = false.
// Diagnostics should still resolve the default endpoint to the first write region.
using GlobalEndpointManager endpointManager = this.Initialize(
useMultipleWriteLocations: false,
enableEndpointDiscovery: true,
isPreferredLocationsListEmpty: false);

// Override account setting to multi-master (server-side) while client did not opt in
this.databaseAccount = LocationCacheTests.CreateDatabaseAccount(
useMultipleWriteLocations: true,
enforceSingleMasterSingleWriteLocation: false);
this.cache.OnDatabaseAccountRead(this.databaseAccount);

string expectedRegionName = this.databaseAccount.WriteLocationsInternal.First().Name;

Assert.AreEqual(expectedRegionName, this.cache.GetLocation(LocationCacheTests.DefaultEndpoint));

Assert.AreEqual(true, this.cache.TryGetLocationForGatewayDiagnostics(LocationCacheTests.DefaultEndpoint, out string regionName));
Assert.AreEqual(expectedRegionName, regionName);

Assert.AreEqual(true, this.cache.TryGetLocationForGatewayDiagnostics(new Uri(LocationCacheTests.DefaultEndpoint, "random/path"), out regionName));
Assert.AreEqual(expectedRegionName, regionName);
}

[TestMethod]
[Owner("ntripician")]
public void ValidateTryGetLocationForGatewayDiagnosticsReturnsFalseForUnknownEndpoint()
{
using GlobalEndpointManager endpointManager = this.Initialize(
useMultipleWriteLocations: true,
enableEndpointDiscovery: true,
isPreferredLocationsListEmpty: false);

// An endpoint that is neither the default endpoint nor any known regional endpoint
Uri unknownEndpoint = new Uri("https://unknown-region.documents.azure.com");

Assert.IsNull(this.cache.GetLocation(unknownEndpoint));

Assert.AreEqual(false, this.cache.TryGetLocationForGatewayDiagnostics(unknownEndpoint, out string regionName));
Assert.IsNull(regionName);
}

[TestMethod]
[Owner("ntripician")]
public void ValidateTryGetLocationForGatewayDiagnosticsOnDefaultEndpointBeforeAccountRead()
{
// Simulate multimaster cache before any account info is populated.
// AvailableWriteLocations will be empty, so GetLocation should return null.
LocationCache uninitializedCache = new LocationCache(
preferredLocations: new ReadOnlyCollection<string>(new List<string> { "location1" }),
defaultEndpoint: LocationCacheTests.DefaultEndpoint,
enableEndpointDiscovery: true,
connectionLimit: 50,
useMultipleWriteLocations: true);

// No OnDatabaseAccountRead called, so AvailableWriteLocations is empty
Assert.IsNull(uninitializedCache.GetLocation(LocationCacheTests.DefaultEndpoint));

// enableMultipleWriteLocations defaults to false until OnDatabaseAccountRead is called
// with a multi-master account, so TryGetLocationForGatewayDiagnostics falls through to
// the single-master path and returns false
Assert.AreEqual(false, uninitializedCache.TryGetLocationForGatewayDiagnostics(LocationCacheTests.DefaultEndpoint, out string regionName));
Assert.IsNull(regionName);
}

[TestMethod]
[Owner("atulk")]
public async Task ValidateRetryOnSessionNotAvailableWithDisableMultipleWriteLocationsAndEndpointDiscoveryDisabled()
Expand Down
Loading