Skip to content
Snippets Groups Projects
Unverified Commit 35b2ce8b authored by Rhys Arkins's avatar Rhys Arkins Committed by GitHub
Browse files

feat: centralised cache (#2472)

Closes #2466 
parent c09c08af
No related branches found
No related tags found
No related merge requests found
...@@ -2,5 +2,6 @@ module.exports = { ...@@ -2,5 +2,6 @@ module.exports = {
globals: { globals: {
logger: true, logger: true,
platform: true, platform: true,
renovateCache: true,
}, },
}; };
const cacache = require('cacache/en');
const os = require('os');
const { DateTime } = require('luxon');
const ghGot = require('../platform/github/gh-got-wrapper'); const ghGot = require('../platform/github/gh-got-wrapper');
const versioning = require('../versioning'); const versioning = require('../versioning');
module.exports = { module.exports = {
getPreset, getPreset,
getPkgReleases, getPkgReleases,
rmAllCache,
}; };
const datasourceCache =
(process.env.RENOVATE_TMPDIR || os.tmpdir()) +
'/renovate-gh-datasource-cache-v1';
async function getCachedResult(repo, type) {
try {
const cacheVal = await cacache.get(datasourceCache, `${repo}-${type}`);
const cachedResult = JSON.parse(cacheVal.data.toString());
if (cachedResult) {
if (DateTime.local() < DateTime.fromISO(cachedResult.expiry)) {
logger.debug(
{ repo, type },
'Returning cached github datasource result'
);
delete cachedResult.expiry;
return cachedResult;
}
// istanbul ignore next
logger.debug('Cache expiry');
}
} catch (err) {
logger.debug('Cache miss');
}
return null;
}
async function setCachedResult(repo, type, res) {
logger.debug({ repo, type }, 'Saving cached github datasource');
await cacache.put(
datasourceCache,
`${repo}-${type}`,
JSON.stringify({ ...res, expiry: DateTime.local().plus({ minutes: 10 }) })
);
}
async function rmAllCache() {
await cacache.rm.all(datasourceCache);
}
const map = new Map(); const map = new Map();
async function getPreset(pkgName, presetName = 'default') { async function getPreset(pkgName, presetName = 'default') {
...@@ -75,11 +31,20 @@ async function getPreset(pkgName, presetName = 'default') { ...@@ -75,11 +31,20 @@ async function getPreset(pkgName, presetName = 'default') {
} }
} }
const cacheNamespace = 'datasource-github';
function getCacheKey(repo, type) {
return `${repo}:${type}`;
}
async function getPkgReleases(purl, config) { async function getPkgReleases(purl, config) {
const { versionScheme } = config || {}; const { versionScheme } = config || {};
const { fullname: repo, qualifiers: options } = purl; const { fullname: repo, qualifiers: options } = purl;
options.ref = options.ref || 'tags';
let versions; let versions;
const cachedResult = await getCachedResult(repo, options.ref); const cachedResult = await renovateCache.get(
cacheNamespace,
getCacheKey(repo, options.ref)
);
if (cachedResult) { if (cachedResult) {
return cachedResult; return cachedResult;
} }
...@@ -117,6 +82,12 @@ async function getPkgReleases(purl, config) { ...@@ -117,6 +82,12 @@ async function getPkgReleases(purl, config) {
version: options.sanitize === 'true' ? isVersion(version) : version, version: options.sanitize === 'true' ? isVersion(version) : version,
gitRef: version, gitRef: version,
})); }));
setCachedResult(repo, options.ref, dependency); const cacheMinutes = 10;
await renovateCache.set(
cacheNamespace,
getCacheKey(repo, options.ref),
dependency,
cacheMinutes
);
return dependency; return dependency;
} }
const cacache = require('cacache/en');
const os = require('os');
const { DateTime } = require('luxon');
module.exports = {
init,
};
function getKey(namespace, key) {
return `${namespace}-${key}`;
}
const renovateCache =
(process.env.RENOVATE_TMPDIR || os.tmpdir()) + '/renovate-cache-v1';
async function get(namespace, key) {
try {
const res = await cacache.get(renovateCache, getKey(namespace, key));
const cachedValue = JSON.parse(res.data.toString());
if (cachedValue) {
if (DateTime.local() < DateTime.fromISO(cachedValue.expiry)) {
logger.debug({ namespace, key }, 'Returning cached value');
return cachedValue.value;
}
// istanbul ignore next
await rm(namespace, key);
}
} catch (err) {
logger.debug({ namespace, key }, 'Cache miss');
}
return null;
}
async function set(namespace, key, value, ttlMinutes) {
logger.debug({ namespace, key }, 'Saving cached value');
await cacache.put(
renovateCache,
getKey(namespace, key),
JSON.stringify({
value,
expiry: DateTime.local().plus({ minutes: ttlMinutes }),
})
);
}
// istanbul ignore next
async function rm(namespace, key) {
logger.debug({ namespace, key }, 'Removing cache entry');
await cacache.rm.entry(renovateCache, getKey(namespace, key));
}
async function rmAll() {
await cacache.rm.all(renovateCache);
}
function init() {
global.renovateCache = global.renovateCache || { get, set, rm, rmAll };
}
...@@ -2,6 +2,7 @@ const is = require('@sindresorhus/is'); ...@@ -2,6 +2,7 @@ const is = require('@sindresorhus/is');
const { initLogger } = require('../../logger'); const { initLogger } = require('../../logger');
const configParser = require('../../config'); const configParser = require('../../config');
const repositoryWorker = require('../repository'); const repositoryWorker = require('../repository');
const cache = require('./cache');
module.exports = { module.exports = {
start, start,
...@@ -10,6 +11,7 @@ module.exports = { ...@@ -10,6 +11,7 @@ module.exports = {
async function start() { async function start() {
initLogger(); initLogger();
cache.init();
try { try {
const config = await configParser.parseConfigs(process.env, process.argv); const config = await configParser.parseConfigs(process.env, process.argv);
delete process.env.GITHUB_TOKEN; delete process.env.GITHUB_TOKEN;
......
const versioning = require('../../../versioning'); const versioning = require('../../../versioning');
const { addReleaseNotes } = require('../release-notes'); const { addReleaseNotes } = require('../release-notes');
const sourceCache = require('./source-cache');
const sourceGithub = require('./source-github'); const sourceGithub = require('./source-github');
module.exports = { module.exports = {
getChangeLogJSON, getChangeLogJSON,
}; };
const cacheNamespace = 'changelog';
function getCacheKey({
versionScheme,
fromVersion,
toVersion,
repositoryUrl,
releases,
}) {
return `${repositoryUrl}-${versionScheme}-${fromVersion}-${toVersion}-${
releases ? releases.map(release => release.version).join('-') : ''
}`;
}
async function getChangeLogJSON(args) { async function getChangeLogJSON(args) {
const { repositoryUrl, versionScheme, fromVersion, toVersion } = args; const { repositoryUrl, versionScheme, fromVersion, toVersion } = args;
if (!repositoryUrl) { if (!repositoryUrl) {
...@@ -20,16 +32,24 @@ async function getChangeLogJSON(args) { ...@@ -20,16 +32,24 @@ async function getChangeLogJSON(args) {
if (!fromVersion || equals(fromVersion, toVersion)) { if (!fromVersion || equals(fromVersion, toVersion)) {
return null; return null;
} }
const cachedResult = await sourceCache.getChangeLogJSON(args); const cachedResult = await renovateCache.get(
cacheNamespace,
getCacheKey(args)
);
if (cachedResult) { if (cachedResult) {
logger.debug('Returning cached changelog');
return cachedResult; return cachedResult;
} }
try { try {
const res = await sourceGithub.getChangeLogJSON({ ...args }); const res = await sourceGithub.getChangeLogJSON({ ...args });
const output = await addReleaseNotes(res); const output = await addReleaseNotes(res);
await sourceCache.setChangeLogJSON(args, output); const cacheMinutes = 60;
await renovateCache.set(
cacheNamespace,
getCacheKey(args),
output,
cacheMinutes
);
return output; return output;
} catch (err) /* istanbul ignore next */ { } catch (err) /* istanbul ignore next */ {
logger.error( logger.error(
......
const os = require('os');
const cacache = require('cacache/en');
const { DateTime } = require('luxon');
module.exports = {
getChangeLogJSON,
setChangeLogJSON,
rmAllCache,
};
function getCache({ manager, depName, fromVersion, toVersion, releases }) {
const tmpdir = process.env.RENOVATE_TMPDIR || os.tmpdir();
const cachePath = tmpdir + '/renovate-cache-changelog-v3';
const cacheKey = `${manager}-${depName}-${fromVersion}-${toVersion}-${
releases ? releases.map(release => release.version).join('-') : ''
}`;
return [cachePath, cacheKey];
}
async function getChangeLogJSON(args) {
const cache = getCache(args);
const { depName } = args;
try {
const cacheVal = await cacache.get(...cache);
logger.trace(`Returning cached version of ${depName}`);
const cachedResult = JSON.parse(cacheVal.data.toString());
if (cachedResult) {
if (DateTime.local() < DateTime.fromISO(cachedResult.expiry)) {
logger.debug('Cache hit');
delete cachedResult.expiry;
return cachedResult;
}
// istanbul ignore next
logger.debug('Cache expiry');
}
} catch (err) {
logger.debug('Cache miss');
}
return null;
}
async function setChangeLogJSON(args, res) {
const cache = getCache(args);
await cacache.put(
...cache,
JSON.stringify({ ...res, expiry: DateTime.local().plus({ hours: 1 }) })
);
}
async function rmAllCache() {
const cache = getCache({});
await cacache.rm.all(cache[0]);
}
...@@ -39,7 +39,7 @@ describe('datasource/github', () => { ...@@ -39,7 +39,7 @@ describe('datasource/github', () => {
}); });
}); });
describe('getPkgReleases', () => { describe('getPkgReleases', () => {
beforeAll(() => github.rmAllCache()); beforeAll(() => global.renovateCache.rmAll());
it('returns cleaned tags', async () => { it('returns cleaned tags', async () => {
const body = [ const body = [
{ name: 'a' }, { name: 'a' },
......
jest.mock('gh-got'); jest.mock('gh-got');
jest.mock('gl-got'); jest.mock('gl-got');
const cache = require('../lib/workers/global/cache');
global.platform = jest.genMockFromModule('../lib/platform/github'); global.platform = jest.genMockFromModule('../lib/platform/github');
global.logger = require('./_fixtures/logger'); global.logger = require('./_fixtures/logger');
cache.init();
...@@ -6,9 +6,6 @@ const endpoints = require('../../../lib/util/endpoints'); ...@@ -6,9 +6,6 @@ const endpoints = require('../../../lib/util/endpoints');
const ghGot = require('../../../lib/platform/github/gh-got-wrapper'); const ghGot = require('../../../lib/platform/github/gh-got-wrapper');
const { getChangeLogJSON } = require('../../../lib/workers/pr/changelog'); const { getChangeLogJSON } = require('../../../lib/workers/pr/changelog');
const {
rmAllCache,
} = require('../../../lib/workers/pr/changelog/source-cache');
const upgrade = { const upgrade = {
depName: 'renovate', depName: 'renovate',
...@@ -39,7 +36,7 @@ describe('workers/pr/changelog', () => { ...@@ -39,7 +36,7 @@ describe('workers/pr/changelog', () => {
platform: 'github', platform: 'github',
endpoint: 'https://api.github.com/', endpoint: 'https://api.github.com/',
}); });
await rmAllCache(); await global.renovateCache.rmAll();
}); });
it('returns null if no fromVersion', async () => { it('returns null if no fromVersion', async () => {
expect( expect(
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment