@@ -3,6 +3,8 @@ import {fetchCached as fetch} from "./fetch.js";
33
44const { GITHUB_TOKEN } = process . env ;
55
6+ let ratelimitReset ;
7+
68export async function fetchGithub ( path , options ) {
79 return ( await requestGithub ( path , options ) ) . body ;
810}
@@ -16,8 +18,26 @@ export async function requestGithub(
1618) {
1719 const url = new URL ( path , "https://api.github.com" ) ;
1820 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+ }
2141 return { headers : response . headers , body : await response . json ( ) } ;
2242}
2343
0 commit comments