@@ -8,6 +8,8 @@ const ExitCodes = {
88} ;
99
1010const PULLS_PER_PAGE = 100 ;
11+ const API_DELAY_MSEC = 2500 ;
12+ const API_MAX_RETRIES = 10 ;
1113const API_RATE_LIMIT = `
1214 rateLimit {
1315 limit
@@ -58,8 +60,12 @@ class DataFetcher {
5860 console . log ( ` [${ item . type } ] ${ item . message } ` ) ;
5961 } ) ;
6062 }
61-
62- async fetchGithub ( query ) {
63+
64+ async delay ( msec ) {
65+ return new Promise ( resolve => setTimeout ( resolve , msec ) ) ;
66+ }
67+
68+ async fetchGithub ( query , retries = 0 ) {
6369 const init = { } ;
6470 init . method = "POST" ;
6571 init . headers = { } ;
@@ -68,13 +74,42 @@ class DataFetcher {
6874 init . headers [ "Authorization" ] = `token ${ process . env . GRAPHQL_TOKEN } ` ;
6975 } else if ( process . env . GITHUB_TOKEN ) {
7076 init . headers [ "Authorization" ] = `token ${ process . env . GITHUB_TOKEN } ` ;
77+ } else {
78+ console . error ( " Unable to find environment variable: `GRAPHQL_TOKEN`. Did you forget to set it in your local environment or a root `.env` file?" ) ;
79+ process . exitCode = buildCommon . ExitCodes . ParseFailure ;
80+ return [ null , null ] ;
7181 }
72-
82+
7383 init . body = JSON . stringify ( {
7484 query,
7585 } ) ;
76-
77- return await fetch ( "https://api.github.com/graphql" , init ) ;
86+
87+ let res = await fetch ( "https://api.github.com/graphql" , init ) ;
88+ let attempt = 0 ;
89+
90+ while ( true ) {
91+ if ( attempt > retries ) {
92+ return [ res , null ] ;
93+ }
94+
95+ if ( res . status === 200 ) {
96+ try {
97+ const json = await res . json ( )
98+ return [ res , json ] ;
99+ }
100+ catch ( err ) {
101+ console . log ( ` Failed due to invalid response body, retrying (${ attempt } /${ retries } )...` ) ;
102+ }
103+ }
104+ else {
105+ console . log ( ` Failed with status ${ res . status } , retrying (${ attempt } /${ retries } )...` ) ;
106+ }
107+
108+ // GitHub API is flaky, so we add an extra delay to let it calm down a bit.
109+ await this . delay ( API_DELAY_MSEC ) ;
110+ attempt += 1 ;
111+ res = await fetch ( "https://api.github.com/graphql" , init ) ;
112+ }
78113 }
79114
80115 async fetchGithubRest ( query ) {
@@ -86,8 +121,12 @@ class DataFetcher {
86121 init . headers [ "Authorization" ] = `token ${ process . env . GRAPHQL_TOKEN } ` ;
87122 } else if ( process . env . GITHUB_TOKEN ) {
88123 init . headers [ "Authorization" ] = `token ${ process . env . GITHUB_TOKEN } ` ;
124+ } else {
125+ console . error ( " Unable to find environment variable: `GRAPHQL_TOKEN`. Did you forget to set it in your local environment or a root `.env` file?" ) ;
126+ process . exitCode = buildCommon . ExitCodes . ParseFailure ;
127+ return null ;
89128 }
90-
129+
91130 return await fetch ( `${ this . api_rest_path } ${ query } ` , init ) ;
92131 }
93132
@@ -99,14 +138,13 @@ class DataFetcher {
99138 }
100139 ` ;
101140
102- const res = await this . fetchGithub ( query ) ;
103- if ( res . status !== 200 ) {
141+ const [ res , data ] = await this . fetchGithub ( query ) ;
142+ if ( res . status !== 200 || data == null ) {
104143 this . _handleResponseErrors ( this . api_repository_id , res ) ;
105144 process . exitCode = ExitCodes . RequestFailure ;
106145 return ;
107146 }
108147
109- const data = await res . json ( ) ;
110148 await this . _logResponse ( data , "_rate_limit" ) ;
111149 this . _handleDataErrors ( data ) ;
112150
@@ -191,14 +229,13 @@ class DataFetcher {
191229 }
192230 console . log ( ` Requesting page ${ page_text } of pull request data (${ after_text } ).` ) ;
193231
194- const res = await this . fetchGithub ( query ) ;
195- if ( res . status !== 200 ) {
232+ const [ res , data ] = await this . fetchGithub ( query , API_MAX_RETRIES ) ;
233+ if ( res . status !== 200 || data == null ) {
196234 this . _handleResponseErrors ( this . api_repository_id , res ) ;
197235 process . exitCode = ExitCodes . RequestFailure ;
198236 return [ ] ;
199237 }
200238
201- const data = await res . json ( ) ;
202239 await this . _logResponse ( data , `data_page_${ page } ` ) ;
203240 this . _handleDataErrors ( data ) ;
204241
0 commit comments