Skip to content

Commit ab51083

Browse files
[INTERNAL] SessionRetry: Adds support to yield immediately after the original attempt when READ_SESSION_NOT_AVAILABLE error is thrown (#5201)
Exposing MaxInRegionRetryCount variable internally so that if it has value of 0 or less than 0 we will not do any retry/delay and yield immediately for READ_SESSION_NOT_AVAILABLE error from the SessionTokenMismtatchInternalRetry policy. [SessionRetryEarlyYield.json](https://github.com/user-attachments/files/20229840/SessionRetryEarlyYield.json) --------- Co-authored-by: Kiran Kumar Kolli <kirankk@microsoft.com>
1 parent ea26d29 commit ab51083

2 files changed

Lines changed: 70 additions & 2 deletions

File tree

Microsoft.Azure.Cosmos/src/SessionRetryOptions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ public SessionRetryOptions()
2525
/// The minimum value is 100ms - this minimum is enforced to provide a way for the local region to catch-up on replication lag. The default value is 500ms - as a recommendation ensure that this value is higher than the steady-state
2626
/// replication latency between the regions you chose
2727
/// </summary>
28-
public TimeSpan MinInRegionRetryTime { get; private set; }
28+
public TimeSpan MinInRegionRetryTime { get; set; }
2929

3030
/// <summary>
3131
/// Sets the maximum number of retries within each region for read and write operations. The minimum value is 1 - the backoff time for the last in-region retry will ensure that the total retry time within the
3232
/// region is at least the min. in-region retry time.
3333
/// </summary>
34-
public int MaxInRegionRetryCount { get; private set; }
34+
public int MaxInRegionRetryCount { get; set; }
3535

3636
/// <summary>
3737
/// hints which guide SDK-internal retry policies on how early to switch retries to a different region. If true, will retry all replicas once and add a minimum delay before switching to the next region.If false, it will

Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SessionRetryOptionsTest.cs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,74 @@ public async Task TestInitAsync()
3434
Assert.IsTrue(this.writeRegionMap.Count() >= 2);
3535

3636
}
37+
38+
[TestMethod]
39+
[DataRow(FaultInjectionOperationType.ReadItem, DisplayName = "No retries for ReadItem when MaxInRegionRetryCount is 0 and EnableRemoteRegionPreferredForSessionRetry is true")]
40+
[DataRow(FaultInjectionOperationType.QueryItem, DisplayName = "No retries for QueryItem when MaxInRegionRetryCount is 0 and and EnableRemoteRegionPreferredForSessionRetry is true")]
41+
[TestCategory("MultiMaster")]
42+
public async Task ReadOrQueryOperationWithMaxInRegionRetryCountZero(FaultInjectionOperationType faultInjectionOperationType)
43+
{
44+
string[] preferredRegions = this.writeRegionMap.Keys.ToArray();
45+
46+
FaultInjectionRule badSessionTokenRule = new FaultInjectionRuleBuilder(
47+
id: "badSessionTokenRule",
48+
condition:
49+
new FaultInjectionConditionBuilder()
50+
.WithOperationType(faultInjectionOperationType)
51+
.WithRegion(preferredRegions[0])
52+
.Build(),
53+
result:
54+
FaultInjectionResultBuilder.GetResultBuilder(FaultInjectionServerErrorType.ReadSessionNotAvailable)
55+
.Build())
56+
.WithDuration(TimeSpan.FromMinutes(10))
57+
.Build();
58+
59+
List<FaultInjectionRule> rules = new List<FaultInjectionRule>() { badSessionTokenRule };
60+
FaultInjector faultInjector = new FaultInjector(rules);
61+
Assert.IsNotNull(faultInjector);
62+
63+
CosmosClientOptions clientOptions = new CosmosClientOptions()
64+
{
65+
EnableRemoteRegionPreferredForSessionRetry = true,
66+
ConsistencyLevel = ConsistencyLevel.Session,
67+
ApplicationPreferredRegions = preferredRegions,
68+
ConnectionMode = ConnectionMode.Direct,
69+
};
70+
71+
// Explicitly set MaxInRegionRetryCount to 0 in SessionRetryOptions
72+
clientOptions.SessionRetryOptions.MaxInRegionRetryCount = 0;
73+
using (CosmosClient faultInjectionClient = new CosmosClient(
74+
connectionString: this.connectionString,
75+
clientOptions: faultInjector.GetFaultInjectionClientOptions(clientOptions)))
76+
{
77+
Database database = faultInjectionClient.GetDatabase(MultiRegionSetupHelpers.dbName);
78+
Container container = await database.CreateContainerIfNotExistsAsync("sessionRetryPolicy", "/id");
79+
string GUID = Guid.NewGuid().ToString();
80+
dynamic testObject = new
81+
{
82+
id = GUID,
83+
name = "customer one",
84+
address = new
85+
{
86+
line1 = "45 new street",
87+
city = "mckinney",
88+
postalCode = "98989",
89+
}
90+
};
91+
92+
ItemResponse<dynamic> response = await container.CreateItemAsync<dynamic>(testObject);
93+
Assert.IsNotNull(response);
94+
95+
OperationExecutionResult executionResult = await this.PerformDocumentOperation(faultInjectionOperationType, container, testObject);
96+
this.ValidateOperationExecutionResult(executionResult, true);
97+
98+
// Assert that only the original attempt happened (no retries)
99+
long hitCount = badSessionTokenRule.GetHitCount();
100+
Assert.AreEqual(4, hitCount, $"There should be only one attempt (no retries) for {faultInjectionOperationType} when MaxInRegionRetryCount is 0 and RemotePreferredRegion is set to true.");
101+
}
102+
103+
}
104+
37105
[TestMethod]
38106
[DataRow(FaultInjectionOperationType.ReadItem, 2, true, DisplayName = "Validate Read Item operation with remote region preferred.")]
39107
[DataRow(FaultInjectionOperationType.QueryItem, 1, true, DisplayName = "Validate Query Item operation with remote region preferred.")]

0 commit comments

Comments
 (0)