From fcd2cb40ea825db2596eb5fa3990cfc17fe00205 Mon Sep 17 00:00:00 2001 From: adickinson72 <44276200+adickinson72@users.noreply.github.com> Date: Sun, 28 Dec 2025 13:41:33 -0600 Subject: [PATCH] fix(rest): correct exponential backoff delay from seconds to milliseconds (#3806) Co-authored-by: Adam Dickinson --- packages/rest/src/Requester.ts | 4 ++-- packages/rest/test/unit/Requester.ts | 11 ++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/rest/src/Requester.ts b/packages/rest/src/Requester.ts index 7a1f74a0..ff97ac9f 100644 --- a/packages/rest/src/Requester.ts +++ b/packages/rest/src/Requester.ts @@ -115,9 +115,9 @@ export async function defaultRequestHandler(endpoint: string, options?: RequestO if (response.ok) return parseResponse(response, asStream); if (!retryCodes.includes(response.status)) await throwFailedRequestError(request, response); - // Retry + // Retry with exponential backoff (in milliseconds) lastStatus = response.status; - await delay(2 ** i * 0.25); + await delay(2 ** i * 250); continue; } diff --git a/packages/rest/test/unit/Requester.ts b/packages/rest/test/unit/Requester.ts index d5c6d96d..c725a42c 100644 --- a/packages/rest/test/unit/Requester.ts +++ b/packages/rest/test/unit/Requester.ts @@ -377,6 +377,8 @@ describe('defaultRequestHandler', () => { }); it('should return a default error if retries are unsuccessful', async () => { + jest.useFakeTimers(); + const responseContent = { error: 'msg' }; const fakeReturnValue = Promise.resolve( Promise.resolve( @@ -392,14 +394,21 @@ describe('defaultRequestHandler', () => { mockFetch.mockReturnValue(fakeReturnValue); - const error = await getError(() => + const errorPromise = getError(() => defaultRequestHandler('http://test.com', {} as RequestOptions), ); + // Fast-forward through all retry delays + await jest.runAllTimersAsync(); + + const error = await errorPromise; + expect(error.message).toBe( 'Could not successfully complete this request after 10 retries, last status code: 429. Check the applicable rate limits for this endpoint.', ); expect(error).toBeInstanceOf(GitbeakerRetryError); + + jest.useRealTimers(); }); it('should return correct properties if request is valid', async () => {