@@ -5,16 +5,16 @@ import fetch from 'node-fetch'
55import { extension } from 'mime-types'
66import credentials from './credentials.js'
77
8- const { username, token, folder } = credentials
8+ const perPage = 100
9+ const retryCount = 10
10+ const retryDelayRateLimit = 6 * 60
11+ const retryDelayOthers = 6
912
10- const startTime = ( new Date ( ) ) . getTime ( )
11- const safetyFactor = 5
12- const requestPerHour = 5000 / safetyFactor
13- let requestNumber = 0
13+ const { username, token, folder } = credentials
1414
15- function wait ( seconds ) {
15+ function delay ( seconds ) {
1616 return new Promise ( resolve => {
17- console . log ( `... wait ${ seconds } s` )
17+ console . log ( `... delay ${ seconds } s` )
1818 setTimeout ( ( ) => {
1919 resolve ( )
2020 } , seconds * 1000 )
@@ -24,22 +24,29 @@ function wait(seconds) {
2424function request ( path , options = { } ) {
2525 return new Promise ( async ( resolve , reject ) => {
2626 const baseUrl = path . substr ( 0 , 4 ) !== 'http' ? 'https://api.github.com' : ''
27- requestNumber ++
28- const allowedRequests = ( ( ( new Date ( ) ) . getTime ( ) ) - startTime ) * ( requestPerHour / 3600 / 1000 )
29- if ( requestNumber > allowedRequests ) await wait ( 1 )
30- console . log ( `Request #${ requestNumber } : ${ baseUrl } ${ path } ` )
31- fetch ( `${ baseUrl } ${ path } ` , {
32- headers : {
33- Authorization : `Token ${ token } `
34- } ,
35- ...options
36- } )
37- . then ( resp => {
38- resolve ( resp )
39- } )
40- . catch ( err => {
41- reject ( err )
42- } )
27+ console . log ( `Request ${ baseUrl } ${ path } ` )
28+ for ( let n = 1 ; n <= retryCount ; n ++ ) {
29+ const resp = await fetch ( `${ baseUrl } ${ path } ` , {
30+ headers : {
31+ Authorization : `Token ${ token } `
32+ } ,
33+ ...options
34+ } )
35+ if ( resp . ok ) {
36+ resolve ( resp )
37+ } else {
38+ const rateLimitRemaining = parseInt ( [ ...resp . headers ] . filter ( obj => obj [ 0 ] === 'x-ratelimit-remaining' ) [ 0 ] [ 1 ] )
39+ const rateLimitLimit = parseInt ( [ ...resp . headers ] . filter ( obj => obj [ 0 ] === 'x-ratelimit-limit' ) [ 0 ] [ 1 ] )
40+ console . log ( `... failed at #${ n } attempt` )
41+ if ( rateLimitRemaining === 0 ) {
42+ console . log ( `... API rate limit of ${ rateLimitLimit } requests per hour exceeded` )
43+ if ( n < retryCount ) await delay ( retryDelayRateLimit )
44+ } else {
45+ if ( n < retryCount ) await delay ( retryDelayOthers )
46+ }
47+ }
48+ }
49+ reject ( )
4350 } )
4451}
4552
@@ -62,11 +69,11 @@ function requestAll(path, options) {
6269 let page = 1
6370 while ( page !== null ) {
6471 const separator = path . indexOf ( '?' ) === - 1 ? '?' : '&'
65- const moreItemsResponse = await request ( `${ path } ${ separator } per_page=100 &page=${ page } ` , options )
72+ const moreItemsResponse = await request ( `${ path } ${ separator } per_page=${ perPage } &page=${ page } ` , options )
6673 const moreItems = await moreItemsResponse . json ( )
6774 if ( moreItems . length ) {
6875 items = [ ...items , ...moreItems ]
69- page = moreItems . length === 100 ? page + 1 : null
76+ page = moreItems . length === perPage ? page + 1 : null
7077 } else {
7178 page = null
7279 }
0 commit comments