fix: retry npmjs when receiving 5xx errors

This commit is contained in:
Rhys Arkins 2018-02-09 10:15:53 +01:00
parent 4fba8373a8
commit 03302a47cc
2 changed files with 22 additions and 5 deletions

View file

@ -3,6 +3,7 @@
const got = require('got'); const got = require('got');
const url = require('url'); const url = require('url');
const ini = require('ini'); const ini = require('ini');
const delay = require('delay');
const getRegistryUrl = require('registry-auth-token/registry-url'); const getRegistryUrl = require('registry-auth-token/registry-url');
const registryAuthToken = require('registry-auth-token'); const registryAuthToken = require('registry-auth-token');
const parse = require('github-url-from-git'); const parse = require('github-url-from-git');
@ -64,7 +65,7 @@ function envReplace(value, env = process.env) {
}); });
} }
async function getDependency(name) { async function getDependency(name, retries = 5) {
logger.trace(`getDependency(${name})`); logger.trace(`getDependency(${name})`);
if (memcache[name]) { if (memcache[name]) {
logger.debug('Returning cached result'); logger.debug('Returning cached result');
@ -148,9 +149,14 @@ async function getDependency(name) {
throw new Error('registry-failure'); throw new Error('registry-failure');
} }
if (err.statusCode >= 500 && err.statusCode < 600) { if (err.statusCode >= 500 && err.statusCode < 600) {
logger.warn({ err }, 'npm registry failure: internal error'); if (retries <= 0) {
logger.warn({ err }, 'npm registry failure: internal error, retries=0');
throw new Error('registry-failure'); throw new Error('registry-failure');
} }
logger.info({ err }, 'npm registry failure: internal error, retrying');
await delay(5000 / retries);
return getDependency(name, retries - 1);
}
logger.warn({ err, name }, 'npm registry failures: Unknown error'); logger.warn({ err, name }, 'npm registry failures: Unknown error');
throw new Error('registry-failure'); throw new Error('registry-failure');
} }

View file

@ -3,6 +3,7 @@ const registryAuthToken = require('registry-auth-token');
const nock = require('nock'); const nock = require('nock');
jest.mock('registry-auth-token'); jest.mock('registry-auth-token');
jest.mock('delay');
const npmResponse = { const npmResponse = {
versions: { versions: {
@ -98,11 +99,21 @@ describe('api/npm', () => {
.reply(503); .reply(503);
let e; let e;
try { try {
await npm.getDependency('foobar'); await npm.getDependency('foobar', 0);
} catch (err) { } catch (err) {
e = err; e = err;
} }
expect(e).toBeDefined(); expect(e.message).toBe('registry-failure');
});
it('should retry when 5xx', async () => {
nock('https://registry.npmjs.org')
.get('/foobar')
.reply(503);
nock('https://registry.npmjs.org')
.get('/foobar')
.reply(200);
const res = await npm.getDependency('foobar');
expect(res).toBe(null);
}); });
it('should throw error for others', async () => { it('should throw error for others', async () => {
nock('https://registry.npmjs.org') nock('https://registry.npmjs.org')