-
Notifications
You must be signed in to change notification settings - Fork 61.6k
/
Copy pathsecondary-ratelimit-retry.ts
44 lines (41 loc) · 1.39 KB
/
secondary-ratelimit-retry.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import { RequestError } from '@octokit/request-error'
const DEFAULT_SLEEPTIME = parseInt(process.env.SECONDARY_RATELIMIT_RETRY_SLEEPTIME || '30000', 10)
const DEFAULT_ATTEMPTS = parseInt(process.env.SECONDARY_RATELIMIT_RETRY_ATTEMPTS || '5', 10)
// Secondary rate limits are responded with a 403. The message will contain
// "You have exceeded a secondary rate limit".
// More info about what they are here:
// https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api?apiVersion=2022-11-28#about-secondary-rate-limits
export async function octoSecondaryRatelimitRetry(
fn: Function,
{ attempts = DEFAULT_ATTEMPTS, sleepTime = DEFAULT_SLEEPTIME } = {},
) {
let tries = 0
while (true) {
try {
return await fn()
} catch (error) {
if (
error instanceof RequestError &&
error.status === 403 &&
/You have exceeded a secondary rate limit/.test(error.message)
) {
if (tries < attempts) {
console.warn(
`Sleeping for ${(sleepTime / 1000).toFixed(1)}s before retrying after ${tries + 1} try`,
)
await sleep(sleepTime)
tries++
continue
} else {
console.warn(`Giving up on retries after ${tries + 1} attempts`)
}
}
throw error
}
}
}
async function sleep(ms: number) {
return new Promise((resolve) => {
setTimeout(resolve, ms)
})
}