@@ -12,6 +12,7 @@ governing permissions and limitations under the License.
12
12
const HttpExponentialBackoff = require ( '../src/HttpExponentialBackoff' )
13
13
const fetchClient = new HttpExponentialBackoff ( )
14
14
const fetchMock = require ( 'node-fetch' )
15
+ const { parseRetryAfterHeader } = require ( '../src/utils' )
15
16
jest . mock ( 'node-fetch' )
16
17
17
18
/**
@@ -25,7 +26,7 @@ jest.mock('node-fetch')
25
26
*/
26
27
function __testRetryOnHelper ( retries , low = 499 , high = 600 ) {
27
28
return jest . fn ( ) . mockImplementation ( function ( attempt , error , response ) {
28
- if ( attempt < retries && ( error !== null || ( response . status > low && response . status < high ) ) ) {
29
+ if ( attempt < retries && ( error !== null || ( response . status > low && response . status < high ) || response . status === 429 ) ) {
29
30
return true
30
31
}
31
32
return false
@@ -41,6 +42,11 @@ function __testRetryOnHelper (retries, low = 499, high = 600) {
41
42
*/
42
43
function __testRetryDelayHelper ( initialDelay ) {
43
44
return jest . fn ( ) . mockImplementation ( function ( attempt , error , response ) {
45
+ const retryAfter = response . headers . get ( 'Retry-After' )
46
+ const timeToWait = parseRetryAfterHeader ( retryAfter )
47
+ if ( ! isNaN ( timeToWait ) ) {
48
+ return timeToWait
49
+ }
44
50
return attempt * initialDelay // 1000, 2000, 4000
45
51
} )
46
52
}
@@ -107,6 +113,19 @@ test('test exponentialBackoff with no retries on 4xx errors and default retry st
107
113
retrySpy . mockRestore ( )
108
114
} )
109
115
116
+ test ( 'test exponentialBackoff with 3 retries on 429 errors and default retry strategy' , async ( ) => {
117
+ const mockDefaultFn = __testRetryOnHelper ( 3 )
118
+ const retrySpy = jest . spyOn ( fetchClient , '__getRetryOn' ) . mockImplementation ( ( retries ) => mockDefaultFn )
119
+ fetchMock . mockResponse ( '429 Too many requests' , {
120
+ status : 429
121
+ } )
122
+ const result = await fetchClient . exponentialBackoff ( 'https://abc1.com/' , { method : 'GET' } , { initialDelayInMillis : 10 } )
123
+ expect ( result . status ) . toBe ( 429 )
124
+ expect ( retrySpy ) . toHaveBeenCalledWith ( 3 )
125
+ expect ( mockDefaultFn ) . toHaveBeenCalledTimes ( 4 )
126
+ retrySpy . mockRestore ( )
127
+ } )
128
+
110
129
test ( 'test exponentialBackoff with 3 retries on 5xx errors and default retry strategy' , async ( ) => {
111
130
const mockDefaultFn = __testRetryOnHelper ( 3 )
112
131
const retrySpy = jest . spyOn ( fetchClient , '__getRetryOn' ) . mockImplementation ( ( retries ) => {
@@ -122,6 +141,20 @@ test('test exponentialBackoff with 3 retries on 5xx errors and default retry str
122
141
retrySpy . mockRestore ( )
123
142
} )
124
143
144
+ test ( 'test exponentialBackoff with 3 retries on errors with default retry strategy and date in Retry-After header' , async ( ) => {
145
+ const spy = jest . spyOn ( global . Date , 'now' ) . mockImplementation ( ( ) => new Date ( 'Mon, 13 Feb 2023 23:59:59 GMT' ) )
146
+ const header = 'Tue, 14 Feb 2023 00:00:00 GMT'
147
+ fetchMock . mockResponse ( '503 Service Unavailable' , {
148
+ status : 503 ,
149
+ headers : {
150
+ 'Retry-After' : header
151
+ }
152
+ } )
153
+ const result = await fetchClient . exponentialBackoff ( 'https://abc2.com/' , { method : 'GET' } , { maxRetries : 2 } )
154
+ expect ( result . status ) . toBe ( 503 )
155
+ expect ( spy ) . toHaveBeenCalledTimes ( 2 )
156
+ } )
157
+
125
158
test ( 'test exponential backoff with success in first attempt and custom retryOptions' , async ( ) => {
126
159
const mockDefaultFn = __testRetryOnHelper ( 2 )
127
160
const retrySpy = jest . spyOn ( fetchClient , '__getRetryOn' ) . mockImplementation ( ( retries ) => {
@@ -215,7 +248,8 @@ test('test exponentialBackoff with default 3 retries on 5xx errors and custom re
215
248
test ( 'test exponentialBackoff with 3 retries on 5xx errors and custom retryDelay' , async ( ) => {
216
249
const mockDefaultFn1 = __testRetryDelayHelper ( 100 )
217
250
fetchMock . mockResponse ( '503 Service Unavailable' , {
218
- status : 503
251
+ status : 503 ,
252
+ headers : { }
219
253
} )
220
254
const result = await fetchClient . exponentialBackoff ( 'https://abc2.com/' , { method : 'GET' } , { maxRetries : 2 } , undefined , mockDefaultFn1 )
221
255
expect ( result . status ) . toBe ( 503 )
0 commit comments