66namespace Microsoft . DurableTask . Worker . Grpc ;
77
88/// <summary>
9- /// Helpers for computing reconnect backoff delays in the gRPC worker.
9+ /// Helpers for computing reconnect and retry backoff delays in the gRPC worker.
1010/// </summary>
11- static class ReconnectBackoff
11+ static class GrpcBackoff
1212{
1313 /// <summary>
1414 /// Creates a random source for reconnect jitter using an explicit random seed so multiple workers on
@@ -32,10 +32,11 @@ public static Random CreateRandom()
3232 /// <param name="baseDelay">The base delay used for the exponential growth.</param>
3333 /// <param name="cap">The maximum delay before jitter is applied.</param>
3434 /// <param name="random">The random source used for jitter.</param>
35+ /// <param name="fullJitter">If true, applies full jitter. If false, applies a smaller jitter that is biased towards the upper bound.</param>
3536 /// <returns>The computed jittered delay.</returns>
36- public static TimeSpan Compute ( int attempt , TimeSpan baseDelay , TimeSpan cap , Random random )
37+ public static TimeSpan Compute ( int attempt , TimeSpan baseDelay , TimeSpan cap , Random random , bool fullJitter )
3738 {
38- if ( baseDelay <= TimeSpan . Zero )
39+ if ( baseDelay <= TimeSpan . Zero || cap <= TimeSpan . Zero )
3940 {
4041 return TimeSpan . Zero ;
4142 }
@@ -48,13 +49,13 @@ public static TimeSpan Compute(int attempt, TimeSpan baseDelay, TimeSpan cap, Ra
4849 // Cap the exponent to avoid overflow in 2^attempt for pathological attempt values.
4950 int safeAttempt = Math . Min ( attempt , 30 ) ;
5051
51- double capMs = Math . Max ( 0 , cap . TotalMilliseconds ) ;
5252 double exponentialMs = baseDelay . TotalMilliseconds * Math . Pow ( 2 , safeAttempt ) ;
53- double upperBoundMs = Math . Min ( capMs , exponentialMs ) ;
53+ double upperBoundMs = Math . Min ( cap . TotalMilliseconds , exponentialMs ) ;
54+
55+ double jitteredMs = fullJitter
56+ ? random . NextDouble ( ) * upperBoundMs
57+ : upperBoundMs + ( random . NextDouble ( ) * ( upperBoundMs * .2 ) ) ;
5458
55- // Full jitter intentionally allows any value in the retry window. The wide spread keeps many
56- // workers that saw the same outage from reconnecting in lockstep against the backend.
57- double jitteredMs = random . NextDouble ( ) * upperBoundMs ;
5859 return TimeSpan . FromMilliseconds ( jitteredMs ) ;
5960 }
6061}
0 commit comments