Skip to content
This repository has been archived by the owner on Jan 12, 2021. It is now read-only.

Commit

Permalink
feat: Add retry with backoff to requests
Browse files Browse the repository at this point in the history
This adds a bit more tolerance to network outages etc. If a 40x status code is recieved from the API
it will not retry as this indicates a bad request – so no need to keep sening the same
request.

There were no end-to-end tests predating this feature so I added some.

Fixes bugsnag/webpack-bugsnag-plugins#17.
  • Loading branch information
bengourley committed Nov 28, 2018
1 parent 511f83d commit ef507e3
Show file tree
Hide file tree
Showing 9 changed files with 540 additions and 18 deletions.
15 changes: 2 additions & 13 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict';

const fs = require('graceful-fs');
const request = require('request');
const request = require('./lib/request');
const path = require('path');
const os = require('os');

Expand Down Expand Up @@ -330,18 +330,7 @@ function sendRequest(args) {
// { options, formData }
const options = args.options
const formData = args.formData
return new Promise((resolve, reject) => {
request.post({
url: options.endpoint,
formData,
}, function (err, res, body) {
if (err || res.statusCode !== 200) {
reject(err || new Error(`${res.statusMessage} (${res.statusCode}) - ${body}`));
} else {
resolve(options);
}
});
});
return request(options.endpoint, formData).then(() => options)
}

/**
Expand Down
32 changes: 32 additions & 0 deletions lib/request.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const request = require('request')
const Backoff = require('backo')
const MAX_ATTEMPTS = 5
const MIN_BACKOFF_INTERVAL = process.env.BUGSNAG_MIN_BACKOFF_INTERVAL || 500
const MAX_BACKOFF_INTERVAL = process.env.BUGSNAG_MAX_BACKOFF_INTERVAL || 5000

module.exports = (url, formData) => {
return new Promise((resolve, reject) => {
const backoff = new Backoff({ min: MIN_BACKOFF_INTERVAL, max: MAX_BACKOFF_INTERVAL })

const onSuccess = () => resolve()
const onError = (err) => {
if (backoff.attempts >= MAX_ATTEMPTS - 1) return reject(err)
if (err.statusCode >= 400 && err.statusCode < 500) return reject(err)
setTimeout(() => req(url, formData, { onSuccess, onError }), backoff.duration())
}

req(url, formData, { onError, onSuccess })
})
}

const req = (url, formData, { onError, onSuccess }) => {
request.post({ url, formData }, function (err, res, body) {
if (err || res.statusCode !== 200) {
err = err || new Error(`${res.statusMessage} (${res.statusCode}) - ${body}`)
if (res.statusCode) err.statusCode = res.statusCode
onError(err)
} else {
onSuccess()
}
})
}
Loading

0 comments on commit ef507e3

Please sign in to comment.