@@ -43,6 +43,13 @@ export interface BackoffOptions {
43
43
* The default is 1 second for RESOURCE_EXHAUSTED errors and 20 millis for other retryable errors.
44
44
*/
45
45
initialIntervalMs ( status : StatusObject ) : number ;
46
+
47
+ /**
48
+ * Function that returns the "maximum" backoff interval based on the returned status.
49
+ *
50
+ * The default is 10 seconds regardless of the status.
51
+ */
52
+ maxIntervalMs ( status : StatusObject ) : number ;
46
53
}
47
54
48
55
/**
@@ -59,17 +66,20 @@ function withDefaultBackoffOptions({
59
66
factor : factor ?? 2 ,
60
67
maxJitter : maxJitter ?? 0.1 ,
61
68
initialIntervalMs : initialIntervalMs ?? defaultInitialIntervalMs ,
69
+ maxIntervalMs ( ) {
70
+ return 10_000 ;
71
+ } ,
62
72
} ;
63
73
}
64
74
65
75
/**
66
76
* Generates the default retry behavior based on given backoff options
67
77
*/
68
78
export function defaultGrpcRetryOptions ( options : Partial < BackoffOptions > = { } ) : GrpcRetryOptions {
69
- const { maxAttempts, factor, maxJitter, initialIntervalMs } = withDefaultBackoffOptions ( options ) ;
79
+ const { maxAttempts, factor, maxJitter, initialIntervalMs, maxIntervalMs } = withDefaultBackoffOptions ( options ) ;
70
80
return {
71
81
delayFunction ( attempt , status ) {
72
- return factor ** attempt * initialIntervalMs ( status ) * jitter ( maxJitter ) ;
82
+ return Math . min ( maxIntervalMs ( status ) , factor ** attempt * initialIntervalMs ( status ) ) * jitter ( maxJitter ) ;
73
83
} ,
74
84
retryableDecider ( attempt , status ) {
75
85
return attempt < maxAttempts && isRetryableError ( status ) ;
@@ -116,7 +126,7 @@ function defaultInitialIntervalMs({ code }: StatusObject) {
116
126
*
117
127
* @param retryOptions Options for the retry interceptor
118
128
*/
119
- export function makeGrpcRetryInterceptor ( { retryableDecider , delayFunction } : GrpcRetryOptions ) : Interceptor {
129
+ export function makeGrpcRetryInterceptor ( retryOptions : GrpcRetryOptions ) : Interceptor {
120
130
return ( options , nextCall ) => {
121
131
let savedSendMessage : any ;
122
132
let savedReceiveMessage : any ;
@@ -147,8 +157,8 @@ export function makeGrpcRetryInterceptor({ retryableDecider, delayFunction }: Gr
147
157
} ;
148
158
149
159
const onReceiveStatus = ( status : StatusObject ) => {
150
- if ( retryableDecider ( attempt , status ) ) {
151
- setTimeout ( retry , delayFunction ( attempt , status ) ) ;
160
+ if ( retryOptions . retryableDecider ( attempt , status ) ) {
161
+ setTimeout ( retry , retryOptions . delayFunction ( attempt , status ) ) ;
152
162
} else {
153
163
savedMessageNext ( savedReceiveMessage ) ;
154
164
// TODO: For reasons that are completely unclear to me, if you pass a handcrafted
0 commit comments