@@ -3,6 +3,8 @@ import {fetchCached as fetch} from "./fetch.js";
3
3
4
4
const { GITHUB_TOKEN } = process . env ;
5
5
6
+ let ratelimitReset ;
7
+
6
8
export async function fetchGithub ( path , options ) {
7
9
return ( await requestGithub ( path , options ) ) . body ;
8
10
}
@@ -16,8 +18,26 @@ export async function requestGithub(
16
18
) {
17
19
const url = new URL ( path , "https://api.github.com" ) ;
18
20
const headers = { ...( authorization && { authorization} ) , accept} ;
19
- const response = await fetch ( url , { headers} ) ;
20
- if ( ! response . ok ) throw new Error ( `failed to fetch ${ url } : ${ response . status } ` ) ;
21
+ let response ;
22
+ for ( let attempt = 0 , maxAttempts = 3 ; attempt < maxAttempts ; ++ attempt ) {
23
+ if ( ratelimitReset ) {
24
+ console . warn ( `x-ratelimit-reset ${ ratelimitReset } ` ) ;
25
+ const ratelimitDelay = new Date ( ratelimitReset * 1000 ) - Date . now ( ) ;
26
+ await new Promise ( ( resolve ) => setTimeout ( resolve , ratelimitDelay ) ) ;
27
+ ratelimitDelay = null ;
28
+ }
29
+ response = await fetch ( url , { headers} ) ;
30
+ const headers = response . headers ;
31
+ if ( headers [ "x-ratelimit-remaining" ] === "0" ) ratelimitReset = headers [ "x-ratelimit-reset" ] ;
32
+ if ( response . ok ) break ;
33
+ if ( headers [ "retry-after" ] ) {
34
+ console . warn ( `retry-after ${ retryAfter } ` ) ;
35
+ const retryDelay = retryAfter * 1000 ;
36
+ await new Promise ( ( resolve ) => setTimeout ( resolve , retryDelay ) ) ;
37
+ continue ;
38
+ }
39
+ throw new Error ( `failed to fetch ${ url } : ${ response . status } ` ) ;
40
+ }
21
41
return { headers : response . headers , body : await response . json ( ) } ;
22
42
}
23
43
0 commit comments