From fd10299a717895c2ac209224cdb01e08768228ce Mon Sep 17 00:00:00 2001
From: Rhys Arkins <rhys@keylocation.sg>
Date: Thu, 16 Nov 2017 22:13:54 +0100
Subject: [PATCH] feat: cache github get requests in memory (#1185)

The existing github wrapper is now extended to cache any get request. The existing pr cache is removed as it is now redundant.
---
 lib/platform/github/gh-got-wrapper.js       | 17 +++++++++++++++--
 lib/platform/github/index.js                |  6 +-----
 test/platform/github/gh-got-wrapper.spec.js |  9 +++++++++
 test/platform/github/index.spec.js          |  2 --
 4 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/lib/platform/github/gh-got-wrapper.js b/lib/platform/github/gh-got-wrapper.js
index 9ebb1cb134..ec00486f0e 100644
--- a/lib/platform/github/gh-got-wrapper.js
+++ b/lib/platform/github/gh-got-wrapper.js
@@ -1,6 +1,8 @@
 const ghGot = require('gh-got');
 const parseLinkHeader = require('parse-link-header');
 
+let cache = {};
+
 // istanbul ignore next
 function sleep(ms) {
   // eslint-disable-next-line promise/avoid-new
@@ -8,9 +10,13 @@ function sleep(ms) {
 }
 
 async function get(path, opts, retries = 5) {
+  const method = opts && opts.method ? opts.method : 'get';
+  if (method === 'get' && cache[path]) {
+    logger.debug({ path }, 'Returning cached result');
+    return cache[path];
+  }
   if (retries === 5) {
-    const method = opts && opts.method ? opts.method.toUpperCase() : 'GET';
-    logger.debug(`${method} ${path}`);
+    logger.debug(`${method.toUpperCase()} ${path}`);
   }
   try {
     if (appMode) {
@@ -39,6 +45,9 @@ async function get(path, opts, retries = 5) {
         );
       }
     }
+    if (method === 'get' && path.startsWith('repos/')) {
+      cache[path] = res;
+    }
     return res;
   } catch (err) {
     if (err.statusCode >= 500 && err.statusCode < 600 && retries > 0) {
@@ -116,4 +125,8 @@ get.setAppMode = function setAppMode(val) {
   appMode = val;
 };
 
+get.reset = function reset() {
+  cache = {};
+};
+
 module.exports = get;
diff --git a/lib/platform/github/index.js b/lib/platform/github/index.js
index ab8bfe9f24..3ef5226937 100644
--- a/lib/platform/github/index.js
+++ b/lib/platform/github/index.js
@@ -73,8 +73,8 @@ async function initRepo(repoName, token, endpoint) {
     process.env.GITHUB_ENDPOINT = endpoint;
   }
   config = {};
+  get.reset();
   config.repoName = repoName;
-  config.prs = {};
   const platformConfig = {};
   let res;
   try {
@@ -536,9 +536,6 @@ async function getPr(prNo) {
   if (!prNo) {
     return null;
   }
-  if (config.prs[prNo]) {
-    return config.prs[prNo];
-  }
   const pr = (await get(`repos/${config.repoName}/pulls/${prNo}`)).body;
   if (!pr) {
     return null;
@@ -599,7 +596,6 @@ async function getPr(prNo) {
       pr.isStale = true;
     }
   }
-  config.prs[prNo] = pr;
   return pr;
 }
 
diff --git a/test/platform/github/gh-got-wrapper.spec.js b/test/platform/github/gh-got-wrapper.spec.js
index 9f88a1f6e1..6f148dd343 100644
--- a/test/platform/github/gh-got-wrapper.spec.js
+++ b/test/platform/github/gh-got-wrapper.spec.js
@@ -175,4 +175,13 @@ describe('platform/gh-got-wrapper', () => {
     const res = await get.post('some-url');
     expect(res.body).toEqual(body);
   });
+  it('returns cached', async () => {
+    get.reset();
+    ghGot.mockReturnValueOnce({
+      body: {},
+    });
+    const res1 = await get('repos/foo');
+    const res2 = await get('repos/foo');
+    expect(res1).toEqual(res2);
+  });
 });
diff --git a/test/platform/github/index.spec.js b/test/platform/github/index.spec.js
index 08bcb1bc30..f5b9315545 100644
--- a/test/platform/github/index.spec.js
+++ b/test/platform/github/index.spec.js
@@ -1039,8 +1039,6 @@ describe('platform/github', () => {
       const pr = await github.getPr(1234);
       expect(pr.canRebase).toBe(true);
       expect(pr).toMatchSnapshot();
-      const cachedPr = await github.getPr(1234);
-      expect(cachedPr).toEqual(pr);
     });
   });
   describe('getPrFiles()', () => {
-- 
GitLab