Skip to content

Commit 14ed414

Browse files
committed
retry with delays depending on rate exceeding or other issues
linked to #1
1 parent 8de33c4 commit 14ed414

File tree

1 file changed

+32
-25
lines changed

1 file changed

+32
-25
lines changed

index.js

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@ import fetch from 'node-fetch'
55
import { extension } from 'mime-types'
66
import 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) {
2424
function 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

Comments
 (0)