From 41c4136632b9391adb3ac53332b312089bc4dc16 Mon Sep 17 00:00:00 2001 From: Szymon Marczak <36894700+szmarczak@users.noreply.github.com> Date: Thu, 15 Apr 2021 15:33:49 +0200 Subject: [PATCH] Add `retry.backoffLimit` option Fixes #1599 --- source/core/calculate-retry-delay.ts | 10 +++++++-- source/core/options.ts | 5 ++++- test/retry.ts | 32 ++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/source/core/calculate-retry-delay.ts b/source/core/calculate-retry-delay.ts index a75b5ed41..b670b561a 100644 --- a/source/core/calculate-retry-delay.ts +++ b/source/core/calculate-retry-delay.ts @@ -2,7 +2,13 @@ import type {RetryFunction} from './options'; type Returns unknown, V> = (...args: Parameters) => V; -const calculateRetryDelay: Returns = ({attemptCount, retryOptions, error, retryAfter, computedValue}) => { +const calculateRetryDelay: Returns = ({ + attemptCount, + retryOptions, + error, + retryAfter, + computedValue +}) => { if (error.name === 'RetryError') { return 1; } @@ -34,7 +40,7 @@ const calculateRetryDelay: Returns = ({attemptCount, retr } const noise = Math.random() * 100; - return ((2 ** (attemptCount - 1)) * 1000) + noise; + return Math.min(((2 ** (attemptCount - 1)) * 1000), retryOptions.backoffLimit) + noise; }; export default calculateRetryDelay; diff --git a/source/core/options.ts b/source/core/options.ts index 339362fa3..f218a66c9 100644 --- a/source/core/options.ts +++ b/source/core/options.ts @@ -293,6 +293,7 @@ export interface RetryOptions { statusCodes: number[]; errorCodes: string[]; calculateDelay: RetryFunction; + backoffLimit: number; maxRetryAfter?: number; } @@ -460,6 +461,7 @@ export interface PaginationOptions { @default 0 */ backoff?: number; + /** The maximum amount of request that should be triggered. Retries on failure are not counted towards this limit. @@ -616,7 +618,8 @@ const defaultInternals: Options['_internals'] = { 'EAI_AGAIN' ], maxRetryAfter: undefined, - calculateDelay: ({computedValue}) => computedValue + calculateDelay: ({computedValue}) => computedValue, + backoffLimit: Number.POSITIVE_INFINITY }, localAddress: undefined, method: 'GET', diff --git a/test/retry.ts b/test/retry.ts index 1a06cbe3e..4b88f5820 100644 --- a/test/retry.ts +++ b/test/retry.ts @@ -565,3 +565,35 @@ test('reuses request options on retry', withServer, async (t, server, got) => { t.is(retryCount, 1); t.is(accept, 'application/json'); }); + +test('respects backoffLimit', withServer, async (t, server, got) => { + let count = 0; + let timestamp = Date.now(); + const data: number[] = []; + + server.get('/', (_request, response) => { + count++; + + const now = Date.now(); + data.push(now - timestamp); + timestamp = now; + + if (count === 3) { + response.end(JSON.stringify(data)); + } else { + response.statusCode = 408; + response.end(); + } + }); + + const body = await got('', { + retry: { + backoffLimit: 0 + } + }).json(); + + t.is(body.length, 3); + t.true(body[0]! < 200); + t.true(body[1]! < 200); + t.true(body[2]! < 200); +});