Skip to content

Commit 0b9a887

Browse files
committed
PPAF : Separate retry timeouts for Reads and Query
1 parent a5c5d23 commit 0b9a887

3 files changed

Lines changed: 77 additions & 10 deletions

File tree

Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicy.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,16 @@ public static HttpTimeoutPolicy GetTimeoutPolicy(
5656
// Data Plane Reads.
5757
else if (documentServiceRequest.IsReadOnlyRequest)
5858
{
59-
return isPartitionLevelFailoverEnabled
60-
? HttpTimeoutPolicyForPartitionFailover.InstanceShouldThrow503OnTimeout
61-
: HttpTimeoutPolicyDefault.InstanceShouldThrow503OnTimeout;
59+
if (isPartitionLevelFailoverEnabled)
60+
{
61+
return documentServiceRequest.OperationType == OperationType.Query
62+
? HttpTimeoutPolicyForPartitionFailover.InstanceShouldThrow503OnTimeoutForQuery
63+
: HttpTimeoutPolicyForPartitionFailover.InstanceShouldThrow503OnTimeoutForReads;
64+
}
65+
else
66+
{
67+
return HttpTimeoutPolicyDefault.InstanceShouldThrow503OnTimeout;
68+
}
6269
}
6370
}
6471

Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyForPartitionFailover.cs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,30 +9,42 @@ namespace Microsoft.Azure.Cosmos
99

1010
internal sealed class HttpTimeoutPolicyForPartitionFailover : HttpTimeoutPolicy
1111
{
12-
public static readonly HttpTimeoutPolicy Instance = new HttpTimeoutPolicyForPartitionFailover(false);
13-
public static readonly HttpTimeoutPolicy InstanceShouldThrow503OnTimeout = new HttpTimeoutPolicyForPartitionFailover(true);
12+
public bool isQuery;
13+
public static readonly HttpTimeoutPolicy InstanceShouldThrow503OnTimeoutForQuery = new HttpTimeoutPolicyForPartitionFailover(true);
14+
public static readonly HttpTimeoutPolicy InstanceShouldThrow503OnTimeoutForReads = new HttpTimeoutPolicyForPartitionFailover(false);
15+
1416
public bool shouldThrow503OnTimeout;
1517
private static readonly string Name = nameof(HttpTimeoutPolicyDefault);
1618

17-
private HttpTimeoutPolicyForPartitionFailover(bool shouldThrow503OnTimeout)
19+
private HttpTimeoutPolicyForPartitionFailover(bool isQuery)
1820
{
19-
this.shouldThrow503OnTimeout = shouldThrow503OnTimeout;
21+
this.isQuery = isQuery;
2022
}
2123

22-
private readonly IReadOnlyList<(TimeSpan requestTimeout, TimeSpan delayForNextRequest)> TimeoutsAndDelays = new List<(TimeSpan requestTimeout, TimeSpan delayForNextRequest)>()
24+
// Timeouts and delays are based on the following rationale:
25+
// For reads: 3 agressive attempts with timeouts of .5s, .5s, and 1s respectively.
26+
// For queries: 3 attempts with timeouts of 5s, 5s, and 10s respectively.
27+
private readonly IReadOnlyList<(TimeSpan requestTimeout, TimeSpan delayForNextRequest)> TimeoutsAndDelaysForReads = new List<(TimeSpan requestTimeout, TimeSpan delayForNextRequest)>()
2328
{
2429
(TimeSpan.FromSeconds(.5), TimeSpan.Zero),
2530
(TimeSpan.FromSeconds(.5), TimeSpan.Zero),
2631
(TimeSpan.FromSeconds(1), TimeSpan.Zero),
2732
};
2833

34+
private readonly IReadOnlyList<(TimeSpan requestTimeout, TimeSpan delayForNextRequest)> TimeoutsAndDelaysForQueries = new List<(TimeSpan requestTimeout, TimeSpan delayForNextRequest)>()
35+
{
36+
(TimeSpan.FromSeconds(5), TimeSpan.Zero),
37+
(TimeSpan.FromSeconds(5), TimeSpan.Zero),
38+
(TimeSpan.FromSeconds(10), TimeSpan.Zero),
39+
};
40+
2941
public override string TimeoutPolicyName => HttpTimeoutPolicyForPartitionFailover.Name;
3042

31-
public override int TotalRetryCount => this.TimeoutsAndDelays.Count;
43+
public override int TotalRetryCount => this.isQuery ? this.TimeoutsAndDelaysForQueries.Count : this.TimeoutsAndDelaysForReads.Count;
3244

3345
public override IEnumerator<(TimeSpan requestTimeout, TimeSpan delayForNextRequest)> GetTimeoutEnumerator()
3446
{
35-
return this.TimeoutsAndDelays.GetEnumerator();
47+
return this.isQuery ? this.TimeoutsAndDelaysForQueries.GetEnumerator() : this.TimeoutsAndDelaysForReads.GetEnumerator();
3648
}
3749

3850
// Assume that it is not safe to retry unless it is a get method.

Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosHttpClientCoreTests.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,54 @@ await TestScenarioAsync(
583583
expectedNumberOfRetrys: 3);
584584
}
585585

586+
[TestMethod]
587+
public void HttpTimeoutPolicyForParitionFailoverForQueries()
588+
{
589+
HttpTimeoutPolicy httpTimeoutPolicyForQuery = HttpTimeoutPolicy.GetTimeoutPolicy(
590+
documentServiceRequest: CosmosHttpClientCoreTests.CreateDocumentServiceRequestByOperation(ResourceType.Document, OperationType.Query),
591+
isPartitionLevelFailoverEnabled: true,
592+
isThinClientEnabled: false);
593+
IEnumerator<(TimeSpan requestTimeout, TimeSpan delayForNextRequest)> availableRetries = httpTimeoutPolicyForQuery.GetTimeoutEnumerator();
594+
595+
int count = 0;
596+
while (availableRetries.MoveNext())
597+
{
598+
if (count <= 1)
599+
{
600+
Assert.AreEqual(new TimeSpan(0,0,5), availableRetries.Current.requestTimeout);
601+
}
602+
else if (count == 2)
603+
{
604+
Assert.AreEqual(new TimeSpan(0, 0, 10), availableRetries.Current.requestTimeout);
605+
}
606+
count++;
607+
}
608+
}
609+
610+
[TestMethod]
611+
public void HttpTimeoutPolicyForParitionFailoverForReads()
612+
{
613+
HttpTimeoutPolicy httpTimeoutPolicyForQuery = HttpTimeoutPolicy.GetTimeoutPolicy(
614+
documentServiceRequest: CosmosHttpClientCoreTests.CreateDocumentServiceRequestByOperation(ResourceType.Document, OperationType.Read),
615+
isPartitionLevelFailoverEnabled: true,
616+
isThinClientEnabled: false);
617+
IEnumerator<(TimeSpan requestTimeout, TimeSpan delayForNextRequest)> availableRetries = httpTimeoutPolicyForQuery.GetTimeoutEnumerator();
618+
619+
int count = 0;
620+
while (availableRetries.MoveNext())
621+
{
622+
if (count <= 1)
623+
{
624+
Assert.AreEqual(new TimeSpan(0, 0,0, 0, 500), availableRetries.Current.requestTimeout);
625+
}
626+
else if (count == 2)
627+
{
628+
Assert.AreEqual(new TimeSpan(0, 0, 1), availableRetries.Current.requestTimeout);
629+
}
630+
count++;
631+
}
632+
}
633+
586634
private static DocumentServiceRequest CreateDocumentServiceRequestByOperation(
587635
ResourceType resourceType,
588636
OperationType operationType)

0 commit comments

Comments
 (0)