Skip to content
This repository was archived by the owner on Oct 10, 2022. It is now read-only.

Commit d0169b7

Browse files
authored
Merge pull request #33 from netlify/fix-rate-limit-again
Retry algorithm tweaks
2 parents b3a670c + 6f10b35 commit d0169b7

File tree

2 files changed

+16
-13
lines changed

2 files changed

+16
-13
lines changed

src/deploy/upload-files.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const pMap = require('p-map')
22
const fs = require('fs')
33
const backoff = require('backoff')
4+
const debug = require('debug')('netlify:deploy')
45

56
module.exports = uploadFiles
67
async function uploadFiles(api, deployId, uploadList, { concurrentUpload, statusCb, maxRetry }) {
@@ -71,8 +72,8 @@ function retryUpload(uploadFn, maxRetry) {
7172
let lastError
7273
const fibonacciBackoff = backoff.fibonacci({
7374
randomisationFactor: 0.5,
74-
initialDelay: 100,
75-
maxDelay: 10000
75+
initialDelay: 5000,
76+
maxDelay: 90000
7677
})
7778
fibonacciBackoff.failAfter(maxRetry)
7879

@@ -93,8 +94,11 @@ function retryUpload(uploadFn, maxRetry) {
9394
.catch(e => {
9495
lastError = e
9596
switch (true) {
96-
case e.status === 408: // request timeout
97+
case e.status >= 400: // observed errors: 408, 401 (4** swallowed), 502
9798
case e.name === 'FetchError': {
99+
debug(`Upload failed... retrying`)
100+
const msg = e.json || e.data
101+
if (msg) debug('O%', msg)
98102
return fibonacciBackoff.backoff()
99103
}
100104
default: {

src/open-api/index.js

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -119,32 +119,31 @@ exports.generateMethod = method => {
119119
// Adapted from:
120120
// https://github.com/netlify/open-api/blob/master/go/porcelain/http/http.go
121121

122-
const MAX_RETRY = 5
122+
const MAX_RETRY = 10
123123
const DEFAULT_RETRY_DELAY = 5000 //ms
124124

125+
let last_retry_delay = DEFAULT_RETRY_DELAY
125126
for (let index = 0; index <= MAX_RETRY; index++) {
127+
debug('Rate limit attempt ' + index + ' for ' + path)
126128
const response = await makeRequest()
127129
if (http.STATUS_CODES[response.status] !== 'Too Many Requests' || index === MAX_RETRY) {
130+
if (index === MAX_RETRY) debug(`Rate limit retry exhausted, aborting request...`)
128131
return response
129132
} else {
130-
debug(`Rate limited, retrying`)
131133
try {
132134
const rateLimitReset = response.headers.get('X-RateLimit-Reset')
133-
debug('rateLimitReset: %O', rateLimitReset)
134135
const resetTime = Number.parseInt(rateLimitReset)
135136
if (!existy(resetTime)) {
136137
debug('Issue getting resetTime: %O', resetTime)
137138
throw new Error('Header missing reset time')
138139
}
139-
debug(`resetTime: ${resetTime}`)
140140
const now = unixNow()
141-
debug(`unixNow(): ${now}`)
142-
const sleepTime = (resetTime - now < 0 ? 0 : resetTime - now) * 1000
143-
debug(`sleeping for ${sleepTime}ms`)
144-
await sleep(sleepTime)
141+
last_retry_delay = ((resetTime - now < 0 ? 0 : resetTime - now) + 1) * 1000 // minimum 1 second
142+
debug(`sleeping for ${last_retry_delay}ms`)
143+
await sleep(last_retry_delay)
145144
} catch (e) {
146-
debug(`sleeping for ${DEFAULT_RETRY_DELAY}ms`)
147-
await sleep(DEFAULT_RETRY_DELAY) // Default to 5 seconds if the header is borked
145+
debug(`sleeping for ${last_retry_delay}ms`)
146+
await sleep(last_retry_delay)
148147
}
149148
}
150149
}

0 commit comments

Comments
 (0)