diff --git a/lib/manager/npm/registry.js b/lib/manager/npm/registry.js index 8f110e3ab2c7486f84a11ca9f6698934d8070758..b150c4a93307ce03d536bfc95dfb9bb9767c0cce 100644 --- a/lib/manager/npm/registry.js +++ b/lib/manager/npm/registry.js @@ -3,6 +3,7 @@ const got = require('got'); const url = require('url'); const ini = require('ini'); +const delay = require('delay'); const getRegistryUrl = require('registry-auth-token/registry-url'); const registryAuthToken = require('registry-auth-token'); 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})`); if (memcache[name]) { logger.debug('Returning cached result'); @@ -148,8 +149,13 @@ async function getDependency(name) { throw new Error('registry-failure'); } if (err.statusCode >= 500 && err.statusCode < 600) { - logger.warn({ err }, 'npm registry failure: internal error'); - throw new Error('registry-failure'); + if (retries <= 0) { + logger.warn({ err }, 'npm registry failure: internal error, retries=0'); + 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'); throw new Error('registry-failure'); diff --git a/test/manager/npm/registry.spec.js b/test/manager/npm/registry.spec.js index 391cd0ca0f0c23e871c3a3b27f481b0a0944be50..88f05a2f70fcea3d5b1d76ce0c1904b899293dcc 100644 --- a/test/manager/npm/registry.spec.js +++ b/test/manager/npm/registry.spec.js @@ -3,6 +3,7 @@ const registryAuthToken = require('registry-auth-token'); const nock = require('nock'); jest.mock('registry-auth-token'); +jest.mock('delay'); const npmResponse = { versions: { @@ -98,11 +99,21 @@ describe('api/npm', () => { .reply(503); let e; try { - await npm.getDependency('foobar'); + await npm.getDependency('foobar', 0); } catch (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 () => { nock('https://registry.npmjs.org')