| 177 | } |
| 178 | |
| 179 | async function secondaryRateLimitRetry(callable, args, maxAttempts = 10, sleepTime = 1000) { |
| 180 | try { |
| 181 | const response = await callable(args) |
| 182 | return response |
| 183 | } catch (err) { |
| 184 | // If you get a secondary rate limit error (403) you'll get a data |
| 185 | // response that includes: |
| 186 | // |
| 187 | // { |
| 188 | // documentation_url: 'https://docs.github.com/en/free-pro-team@latest/rest/overview/resources-in-the-rest-api#secondary-rate-limits', |
| 189 | // message: 'You have exceeded a secondary rate limit. Please wait a few minutes before you try again.' |
| 190 | // } |
| 191 | // |
| 192 | // Let's look for that an manually self-recurse, under certain conditions |
| 193 | const lookFor = 'You have exceeded a secondary rate limit.' |
| 194 | if ( |
| 195 | err.status && |
| 196 | err.status === 403 && |
| 197 | err.response?.data?.message.includes(lookFor) && |
| 198 | maxAttempts > 0 |
| 199 | ) { |
| 200 | console.warn( |
| 201 | `Got secondary rate limit blocked. Sleeping for ${ |
| 202 | sleepTime / 1000 |
| 203 | } seconds. (attempts left: ${maxAttempts})` |
| 204 | ) |
| 205 | return new Promise((resolve) => { |
| 206 | setTimeout(() => { |
| 207 | resolve(secondaryRateLimitRetry(callable, args, maxAttempts - 1, sleepTime * 2)) |
| 208 | }, sleepTime) |
| 209 | }) |
| 210 | } |
| 211 | |
| 212 | throw err |
| 213 | } |
| 214 | } |