@@ -157,7 +157,7 @@ export async function getPathsWithMatchingStrings(strArr, org, repo) {
157
157
158
158
async function searchCode ( q , perPage , currentPage ) {
159
159
try {
160
- const { data } = await github . rest . search . code ( {
160
+ const { data } = await secondaryRateLimitRetry ( github . rest . search . code , {
161
161
q,
162
162
per_page : perPage ,
163
163
page : currentPage ,
@@ -169,3 +169,41 @@ async function searchCode(q, perPage, currentPage) {
169
169
throw err
170
170
}
171
171
}
172
+
173
+ async function secondaryRateLimitRetry ( callable , args , maxAttempts = 5 ) {
174
+ try {
175
+ const response = await callable ( args )
176
+ return response
177
+ } catch ( err ) {
178
+ // If you get a secondary rate limit error (403) you'll get a data
179
+ // response that includes:
180
+ //
181
+ // {
182
+ // documentation_url: 'https://docs.github.com/en/free-pro-team@latest/rest/overview/resources-in-the-rest-api#secondary-rate-limits',
183
+ // message: 'You have exceeded a secondary rate limit. Please wait a few minutes before you try again.'
184
+ // }
185
+ //
186
+ // Let's look for that an manually self-recurse, under certain conditions
187
+ const lookFor = 'You have exceeded a secondary rate limit.'
188
+ const sleepTime = 5000 // ms
189
+ if (
190
+ err . status &&
191
+ err . status === 403 &&
192
+ err . response ?. data ?. message . includes ( lookFor ) &&
193
+ maxAttempts > 0
194
+ ) {
195
+ console . warn (
196
+ `Got secondary rate limit blocked. Sleeping for ${
197
+ sleepTime / 1000
198
+ } seconds. (attempts left: ${ maxAttempts } )`
199
+ )
200
+ return new Promise ( ( resolve ) => {
201
+ setTimeout ( ( ) => {
202
+ resolve ( secondaryRateLimitRetry ( callable , args , maxAttempts - 1 ) )
203
+ } , sleepTime )
204
+ } )
205
+ }
206
+
207
+ throw err
208
+ }
209
+ }
0 commit comments