diff --git a/src/index.ts b/src/index.ts index ff951c59..e23cc03c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -137,8 +137,11 @@ export function throttling(octokit: Octokit, octokitOptions: OctokitOptions) { return { wantRetry, retryAfter }; } if ( - error.response.headers != null && - error.response.headers["x-ratelimit-remaining"] === "0" + (error.response.headers != null && + error.response.headers["x-ratelimit-remaining"] === "0") || + (error.response.data?.errors ?? []).some( + (error: any) => error.type === "RATE_LIMITED", + ) ) { // The user has used all their allowed calls for the current time period (REST and GraphQL) // https://docs.github.com/en/rest/reference/rate-limit (REST) @@ -148,7 +151,9 @@ export function throttling(octokit: Octokit, octokitOptions: OctokitOptions) { ~~error.response.headers["x-ratelimit-reset"] * 1000, ).getTime(); const retryAfter = Math.max( - Math.ceil((rateLimitReset - Date.now()) / 1000), + // Add one second so we retry _after_ the reset time + // https://docs.github.com/en/rest/overview/resources-in-the-rest-api?apiVersion=2022-11-28#exceeding-the-rate-limit + Math.ceil((rateLimitReset - Date.now()) / 1000) + 1, 0, ); const wantRetry = await emitter.trigger( diff --git a/test/events.test.ts b/test/events.test.ts index 51421459..16e8a16b 100644 --- a/test/events.test.ts +++ b/test/events.test.ts @@ -133,8 +133,8 @@ describe("Events", function () { throttle: { onRateLimit: (retryAfter, options, octokitFromOptions) => { expect(octokit).toBe(octokitFromOptions); - expect(retryAfter).toBeLessThan(32); - expect(retryAfter).toBeGreaterThan(28); + expect(retryAfter).toBeLessThan(33); + expect(retryAfter).toBeGreaterThan(29); expect(options).toMatchObject({ method: "GET", url: "/route2", diff --git a/test/retry.test.ts b/test/retry.test.ts index f350952a..ced754e3 100644 --- a/test/retry.test.ts +++ b/test/retry.test.ts @@ -250,7 +250,9 @@ describe("Retry", function () { { status: 200, headers: { - "x-ratelimit-remaining": "0", + // should retry based on response body, not header + // https://github.com/octokit/plugin-throttling.js/issues/632 + "x-ratelimit-remaining": "1", "x-ratelimit-reset": "123", }, data: { errors: [{ type: "RATE_LIMITED" }] }, @@ -300,7 +302,7 @@ describe("Retry", function () { { status: 200, headers: { - "x-ratelimit-remaining": "0", + "x-ratelimit-remaining": "1", "x-ratelimit-reset": "123", }, data: { errors: [{ type: "RATE_LIMITED" }] },