Skip to content

Commit fd68e4c

Browse files
committed
Handle GitHub API rate limits in script
1 parent c8d5fc6 commit fd68e4c

File tree

1 file changed

+30
-1
lines changed

1 file changed

+30
-1
lines changed

docs/scripts/update-contributors.js

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import fs from "node:fs/promises";
2+
import timers from "node:timers/promises";
23
import { URL } from "node:url";
34

45
const MAINTAINERS = {
@@ -227,9 +228,35 @@ async function fetchUserInfo(username) {
227228
"X-GitHub-Api-Version": "2022-11-28",
228229
},
229230
});
231+
230232
if (!res.ok) {
233+
const retryAfter = res.headers.get("retry-after"); // seconds
234+
const ratelimitRemaining = res.headers.get("x-ratelimit-remaining"); // quantity of requests remaining
235+
const ratelimitReset = res.headers.get("x-ratelimit-reset"); // UTC epoch seconds
236+
237+
if (retryAfter || ratelimitRemaining === "0" || ratelimitReset) {
238+
// See https://docs.github.com/en/rest/using-the-rest-api/best-practices-for-using-the-rest-api?apiVersion=2022-11-28#handle-rate-limit-errors-appropriately
239+
console.warn("Rate limited by GitHub API");
240+
241+
let timeoutInMilliseconds;
242+
if (retryAfter) {
243+
timeoutInMilliseconds = retryAfter * 1000;
244+
} else if (ratelimitRemaining === "0") {
245+
if (ratelimitReset) {
246+
timeoutInMilliseconds = ratelimitReset * 1000 - Date.now();
247+
} else {
248+
timeoutInMilliseconds = 60 * 1000;
249+
}
250+
}
251+
252+
await timers.setTimeout(timeoutInMilliseconds);
253+
254+
return await fetchUserInfo(username);
255+
}
256+
231257
throw new UserFetchError(`${res.url} responded with ${res.status}`, res);
232258
}
259+
233260
return await res.json();
234261
}
235262

@@ -282,4 +309,6 @@ async function main() {
282309
}
283310
}
284311

285-
main();
312+
if (import.meta.main) {
313+
main();
314+
}

0 commit comments

Comments
 (0)