fix: react on both type and message-based rate-limit signals (#4440)

Co-authored-by: Alexandr <qwerty541zxc@gmail.com>
This commit is contained in:
Ophelia Goldstein
2025-10-25 12:37:28 +02:00
committed by martin-mfg
co-authored by Alexandr
parent cd40532db7
commit ab2b0f4c97
2 changed files with 37 additions and 3 deletions
+9 -3
View File
@@ -25,12 +25,14 @@ const retryer = async (fetcher, variables, retries = 0) => {
if (!RETRIES) {
throw new CustomError("No GitHub API tokens found", CustomError.NO_TOKENS);
}
if (retries > RETRIES) {
throw new CustomError(
"Downtime due to GitHub API rate limiting",
CustomError.MAX_RETRY,
);
}
try {
// try to fetch with the first token since RETRIES is 0 index i'm adding +1
let response = await fetcher(
@@ -39,12 +41,16 @@ const retryer = async (fetcher, variables, retries = 0) => {
retries,
);
// prettier-ignore
const isRateExceeded = response.data.errors && response.data.errors[0].type === "RATE_LIMITED";
// react on both type and message-based rate-limit signals.
const errors = response?.data?.errors;
const errorType = errors?.[0]?.type;
const errorMsg = errors?.[0]?.message || "";
const isRateLimited =
(errors && errorType === "RATE_LIMITED") || /rate limit/i.test(errorMsg);
// if rate limit is hit increase the RETRIES and recursively call the retryer
// with username, and current RETRIES
if (isRateExceeded) {
if (isRateLimited) {
logger.log(`PAT_${retries + 1} Failed due to rate limiting`);
retries++;
// directly return from the function
+28
View File
@@ -25,6 +25,27 @@ const fetcherFailOnSecondTry = jest.fn((_vars, _token, retries) => {
});
});
const fetcherFailWithMessageBasedRateLimitErr = jest.fn(
(_vars, _token, retries) => {
return new Promise((res) => {
// faking rate limit
if (retries < 1) {
return res({
data: {
errors: [
{
type: "ASDF",
message: "API rate limit already exceeded for user ID 11111111",
},
],
},
});
}
return res({ data: "ok" });
});
},
);
describe("Test Retryer", () => {
it("retryer should return value and have zero retries on first try", async () => {
let res = await retryer(fetcher, {});
@@ -40,6 +61,13 @@ describe("Test Retryer", () => {
expect(res).toStrictEqual({ data: "ok" });
});
it("retryer should return value and have 2 retries with message based rate limit error", async () => {
let res = await retryer(fetcherFailWithMessageBasedRateLimitErr, {});
expect(fetcherFailWithMessageBasedRateLimitErr).toBeCalledTimes(2);
expect(res).toStrictEqual({ data: "ok" });
});
it("retryer should throw specific error if maximum retries reached", async () => {
try {
await retryer(fetcherFail, {});