From 03302a47ccd3f244674a9ade8c530b956475f3b7 Mon Sep 17 00:00:00 2001
From: Rhys Arkins <rhys@arkins.net>
Date: Fri, 9 Feb 2018 10:15:53 +0100
Subject: [PATCH] fix: retry npmjs when receiving 5xx errors

---
 lib/manager/npm/registry.js       | 12 +++++++++---
 test/manager/npm/registry.spec.js | 15 +++++++++++++--
 2 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/lib/manager/npm/registry.js b/lib/manager/npm/registry.js
index 8f110e3ab2..b150c4a933 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 391cd0ca0f..88f05a2f70 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')
-- 
GitLab