@@ -417,14 +417,17 @@ export abstract class APIClient {
417
417
418
418
if ( ! response . ok ) {
419
419
if ( retriesRemaining && this . shouldRetry ( response ) ) {
420
+ const retryMessage = `retrying, ${ retriesRemaining } attempts remaining` ;
421
+ debug ( `response (error; ${ retryMessage } )` , response . status , url , responseHeaders ) ;
420
422
return this . retryRequest ( options , retriesRemaining , responseHeaders ) ;
421
423
}
422
424
423
425
const errText = await response . text ( ) . catch ( ( e ) => castToError ( e ) . message ) ;
424
426
const errJSON = safeJSON ( errText ) ;
425
427
const errMessage = errJSON ? undefined : errText ;
428
+ const retryMessage = retriesRemaining ? `(error; no more retries left)` : `(error; not retryable)` ;
426
429
427
- debug ( ' response' , response . status , url , responseHeaders , errMessage ) ;
430
+ debug ( ` response (error; ${ retryMessage } )` , response . status , url , responseHeaders , errMessage ) ;
428
431
429
432
const err = this . makeStatusError ( response . status , errJSON , errMessage , responseHeaders ) ;
430
433
throw err ;
@@ -529,11 +532,21 @@ export abstract class APIClient {
529
532
retriesRemaining : number ,
530
533
responseHeaders ?: Headers | undefined ,
531
534
) : Promise < APIResponseProps > {
532
- // About the Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After
533
535
let timeoutMillis : number | undefined ;
536
+
537
+ // Note the `retry-after-ms` header may not be standard, but is a good idea and we'd like proactive support for it.
538
+ const retryAfterMillisHeader = responseHeaders ?. [ 'retry-after-ms' ] ;
539
+ if ( retryAfterMillisHeader ) {
540
+ const timeoutMs = parseFloat ( retryAfterMillisHeader ) ;
541
+ if ( ! Number . isNaN ( timeoutMs ) ) {
542
+ timeoutMillis = timeoutMs ;
543
+ }
544
+ }
545
+
546
+ // About the Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After
534
547
const retryAfterHeader = responseHeaders ?. [ 'retry-after' ] ;
535
- if ( retryAfterHeader ) {
536
- const timeoutSeconds = parseInt ( retryAfterHeader ) ;
548
+ if ( retryAfterHeader && ! timeoutMillis ) {
549
+ const timeoutSeconds = parseFloat ( retryAfterHeader ) ;
537
550
if ( ! Number . isNaN ( timeoutSeconds ) ) {
538
551
timeoutMillis = timeoutSeconds * 1000 ;
539
552
} else {
@@ -543,12 +556,7 @@ export abstract class APIClient {
543
556
544
557
// If the API asks us to wait a certain amount of time (and it's a reasonable amount),
545
558
// just do what it says, but otherwise calculate a default
546
- if (
547
- ! timeoutMillis ||
548
- ! Number . isInteger ( timeoutMillis ) ||
549
- timeoutMillis <= 0 ||
550
- timeoutMillis > 60 * 1000
551
- ) {
559
+ if ( ! ( timeoutMillis && 0 <= timeoutMillis && timeoutMillis < 60 * 1000 ) ) {
552
560
const maxRetries = options . maxRetries ?? this . maxRetries ;
553
561
timeoutMillis = this . calculateDefaultRetryTimeoutMillis ( retriesRemaining , maxRetries ) ;
554
562
}
0 commit comments