Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Routing: Adds ExcludeRegions Feature to RequestOptions #4128

Merged
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
2a219e8
adds excludeRegions
NaluTripician Oct 16, 2023
a101ec6
Merge branch 'master' into users/nalutripician/excludeRegions
NaluTripician Oct 17, 2023
fb7637a
suggested changes
NaluTripician Oct 17, 2023
b2b0294
removed unused usings
NaluTripician Oct 17, 2023
979af68
fixed blank line error
NaluTripician Oct 17, 2023
9606e6c
removed using
NaluTripician Oct 20, 2023
63f8a83
Merge branch 'master' into users/nalutripician/excludeRegions
NaluTripician Oct 20, 2023
0db8c43
update contracts
NaluTripician Oct 20, 2023
e7b6fdd
fixed test
NaluTripician Oct 23, 2023
736dacc
reverted automatic changes to BaselineTests
NaluTripician Oct 24, 2023
8a43fad
Merge branch 'master' into users/nalutripician/excludeRegions
NaluTripician Oct 24, 2023
37de363
Merge branch 'master' into users/nalutripician/excludeRegions
NaluTripician Oct 25, 2023
bcc75e3
requested changes
NaluTripician Oct 26, 2023
376bc74
bug fix
NaluTripician Oct 26, 2023
3500bbd
Merge branch 'master' into users/nalutripician/excludeRegions
NaluTripician Oct 27, 2023
bb3ac39
Merge branch 'master' into users/nalutripician/excludeRegions
NaluTripician Oct 30, 2023
1a040e2
PPOF test fix
NaluTripician Oct 30, 2023
2bda1a3
Merge branch 'master' into users/nalutripician/excludeRegions
NaluTripician Oct 31, 2023
54f4330
Merge branch 'master' into users/nalutripician/excludeRegions
NaluTripician Nov 2, 2023
245b32e
Merge branch 'master' into users/nalutripician/excludeRegions
NaluTripician Nov 3, 2023
4f35050
Merge branch 'master' into users/nalutripician/excludeRegions
NaluTripician Nov 8, 2023
4f6844d
Merge branch 'master' into users/nalutripician/excludeRegions
NaluTripician Nov 8, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 5 additions & 4 deletions Microsoft.Azure.Cosmos/src/ClientRetryPolicy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -243,9 +243,9 @@ public void OnBeforeSendRequest(DocumentServiceRequest request)
if (statusCode == HttpStatusCode.NotFound
&& subStatusCode == SubStatusCodes.ReadSessionNotAvailable)
{
return this.ShouldRetryOnSessionNotAvailable();
return this.ShouldRetryOnSessionNotAvailable(this.documentServiceRequest);
}

NaluTripician marked this conversation as resolved.
Show resolved Hide resolved
// Received 503 due to client connect timeout or Gateway
if (statusCode == HttpStatusCode.ServiceUnavailable
&& ClientRetryPolicy.IsRetriableServiceUnavailable(subStatusCode))
Expand Down Expand Up @@ -334,7 +334,7 @@ private static bool IsRetriableServiceUnavailable(SubStatusCodes? subStatusCode)
return ShouldRetryResult.RetryAfter(retryDelay);
}

private ShouldRetryResult ShouldRetryOnSessionNotAvailable()
private ShouldRetryResult ShouldRetryOnSessionNotAvailable(DocumentServiceRequest request)
{
this.sessionTokenRetryCount++;

Expand All @@ -347,7 +347,8 @@ private ShouldRetryResult ShouldRetryOnSessionNotAvailable()
{
if (this.canUseMultipleWriteLocations)
{
ReadOnlyCollection<Uri> endpoints = this.isReadRequest ? this.globalEndpointManager.ReadEndpoints : this.globalEndpointManager.WriteEndpoints;
ReadOnlyCollection<Uri> endpoints = this.isReadRequest ?
this.globalEndpointManager.GetApplicableReadEndpoints(request) : this.globalEndpointManager.GetApplicableWriteEndpoints(request);

if (this.sessionTokenRetryCount > endpoints.Count)
{
Expand Down
4 changes: 3 additions & 1 deletion Microsoft.Azure.Cosmos/src/Handler/RequestMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,8 @@ internal DocumentServiceRequest ToDocumentServiceRequest()
{
this.DocumentServiceRequest.RouteTo(this.PartitionKeyRangeId);
}


this.DocumentServiceRequest.RequestContext.ExcludeRegions = this.RequestOptions?.ExcludeRegions;
this.OnBeforeRequestHandler(this.DocumentServiceRequest);
return this.DocumentServiceRequest;
}
Expand All @@ -299,6 +300,7 @@ private static Headers CreateHeaders()

private void OnBeforeRequestHandler(DocumentServiceRequest serviceRequest)
{
serviceRequest.RequestContext.ExcludeRegions = this.RequestOptions?.ExcludeRegions;
this.OnBeforeSendRequestActions?.Invoke(serviceRequest);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
namespace Microsoft.Azure.Cosmos
{
using System;
using System.ComponentModel;
using System.Text;
using Microsoft.Azure.Cosmos.CosmosElements;
using Microsoft.Azure.Cosmos.Query;
Expand Down
5 changes: 5 additions & 0 deletions Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ public class RequestOptions
/// </summary>
public CosmosThresholdOptions CosmosThresholdOptions { get; set; }

/// <summary>
/// List of regions to be excluded routing the request to.
NaluTripician marked this conversation as resolved.
Show resolved Hide resolved
/// </summary>
public List<string> ExcludeRegions { get; set; }
kirankumarkolli marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// Gets or sets the boolean to use effective partition key routing in the cosmos db request.
/// </summary>
Expand Down
10 changes: 10 additions & 0 deletions Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,16 @@ public string GetLocation(Uri endpoint)
return this.locationCache.GetLocation(endpoint);
}

public ReadOnlyCollection<Uri> GetApplicableWriteEndpoints(DocumentServiceRequest request)
{
return this.locationCache.GetApplicableWriteEndpoints(request);
}

public ReadOnlyCollection<Uri> GetApplicableReadEndpoints(DocumentServiceRequest request)
{
return this.locationCache.GetApplicableReadEndpoints(request);
}

public bool TryGetLocationForGatewayDiagnostics(Uri endpoint, out string regionName)
{
return this.locationCache.TryGetLocationForGatewayDiagnostics(endpoint, out regionName);
Expand Down
78 changes: 77 additions & 1 deletion Microsoft.Azure.Cosmos/src/Routing/LocationCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -276,14 +276,90 @@ public Uri ResolveServiceEndpoint(DocumentServiceRequest request)
}
else
{
ReadOnlyCollection<Uri> endpoints = request.OperationType.IsWriteOperation() ? this.WriteEndpoints : this.ReadEndpoints;
ReadOnlyCollection<Uri> endpoints =
request.OperationType.IsWriteOperation() ? this.GetApplicableWriteEndpoints(request) : this.GetApplicableReadEndpoints(request);
locationEndpointToRoute = endpoints[locationIndex % endpoints.Count];
}

request.RequestContext.RouteToLocation(locationEndpointToRoute);
return locationEndpointToRoute;
}

public ReadOnlyCollection<Uri> GetApplicableWriteEndpoints(DocumentServiceRequest request)
{
ReadOnlyCollection<Uri> writeEndpoints = this.WriteEndpoints;
NaluTripician marked this conversation as resolved.
Show resolved Hide resolved

if (request.RequestContext.ExcludeRegions == null || request.RequestContext.ExcludeRegions.Count == 0)
{
return writeEndpoints;
}

return this.GetApplicableEndpoints(
writeEndpoints,
this.locationInfo.AvailableWriteEndpointByLocation,
this.defaultEndpoint,
request.RequestContext.ExcludeRegions);
}

public ReadOnlyCollection<Uri> GetApplicableReadEndpoints(DocumentServiceRequest request)
{
ReadOnlyCollection<Uri> readEndpoints = this.ReadEndpoints;

if (request.RequestContext.ExcludeRegions == null || request.RequestContext.ExcludeRegions.Count == 0)
{
return readEndpoints;
}

return this.GetApplicableEndpoints(
readEndpoints,
this.locationInfo.AvailableReadEndpointByLocation,
this.defaultEndpoint,
request.RequestContext.ExcludeRegions);
}

/// <summary>
/// Gets applicable endpoints for a request, if there are no applicable endpoints, returns the fallback endpoint
/// </summary>
/// <param name="endpoints"></param>
/// <param name="regionNameByEndpoint"></param>
/// <param name="fallbackEndpoint"></param>
/// <param name="excludeRegions"></param>
/// <returns>a list of applicable endpoints for a request</returns>
private ReadOnlyCollection<Uri> GetApplicableEndpoints(
IReadOnlyList<Uri> endpoints,
NaluTripician marked this conversation as resolved.
Show resolved Hide resolved
ReadOnlyDictionary<string, Uri> regionNameByEndpoint,
Uri fallbackEndpoint,
IReadOnlyList<string> excludeRegions)
{
RegionNameMapper mapper = new RegionNameMapper();
NaluTripician marked this conversation as resolved.
Show resolved Hide resolved
List<Uri> applicableEndpoints = new List<Uri>();
NaluTripician marked this conversation as resolved.
Show resolved Hide resolved
HashSet<Uri> excludeUris = new HashSet<Uri>();

foreach (string region in excludeRegions)
{
string normalizedRegionName = mapper.GetCosmosDBRegionName(region);
if (regionNameByEndpoint.ContainsKey(normalizedRegionName))
{
excludeUris.Add(regionNameByEndpoint[normalizedRegionName]);
}
}

foreach (Uri endpoint in endpoints)
{
if (!excludeUris.Contains(endpoint))
{
applicableEndpoints.Add(endpoint);
}
}

if (applicableEndpoints.Count == 0)
{
applicableEndpoints.Add(fallbackEndpoint);
}

return new ReadOnlyCollection<Uri>(applicableEndpoints);
}

public bool ShouldRefreshEndpoints(out bool canRefreshInBackground)
{
canRefreshInBackground = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7986,6 +7986,18 @@
"Attributes": [],
"MethodInfo": "System.Collections.Generic.IReadOnlyDictionary`2[System.String,System.Object] Properties;CanRead:True;CanWrite:True;System.Collections.Generic.IReadOnlyDictionary`2[System.String,System.Object] get_Properties();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_Properties(System.Collections.Generic.IReadOnlyDictionary`2[System.String,System.Object]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
},
"System.Collections.Generic.List`1[System.String] ExcludeRegions": {
"Type": "Property",
"Attributes": [],
"MethodInfo": "System.Collections.Generic.List`1[System.String] ExcludeRegions;CanRead:True;CanWrite:True;System.Collections.Generic.List`1[System.String] get_ExcludeRegions();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_ExcludeRegions(System.Collections.Generic.List`1[System.String]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
},
"System.Collections.Generic.List`1[System.String] get_ExcludeRegions()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": {
"Type": "Method",
"Attributes": [
"CompilerGeneratedAttribute"
],
"MethodInfo": "System.Collections.Generic.List`1[System.String] get_ExcludeRegions();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
},
"System.String get_IfMatchEtag()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": {
"Type": "Method",
"Attributes": [
Expand Down Expand Up @@ -8029,6 +8041,13 @@
],
"MethodInfo": "Void set_CosmosThresholdOptions(Microsoft.Azure.Cosmos.CosmosThresholdOptions);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
},
"Void set_ExcludeRegions(System.Collections.Generic.List`1[System.String])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": {
"Type": "Method",
"Attributes": [
"CompilerGeneratedAttribute"
],
"MethodInfo": "Void set_ExcludeRegions(System.Collections.Generic.List`1[System.String]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
},
"Void set_IfMatchEtag(System.String)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": {
"Type": "Method",
"Attributes": [
Expand Down