renovate
Version:
Automated dependency updates. Flexible so you don't need to be.
92 lines • 3.66 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.cache = cache;
const tslib_1 = require("tslib");
const is_1 = tslib_1.__importDefault(require("@sindresorhus/is"));
const luxon_1 = require("luxon");
const global_1 = require("../../../config/global");
const logger_1 = require("../../../logger");
const decorator_1 = require("../../decorator");
const mutex_1 = require("../../mutex");
const ttl_1 = require("./ttl");
const packageCache = tslib_1.__importStar(require("."));
/**
* caches the result of a decorated method.
*/
function cache({ namespace, key, cacheable = () => true, ttlMinutes = 30, }) {
return (0, decorator_1.decorate)(async ({ args, instance, callback, methodName }) => {
const cachePrivatePackages = global_1.GlobalConfig.get('cachePrivatePackages', false);
const isCacheable = cachePrivatePackages || cacheable.apply(instance, args);
if (!isCacheable) {
return callback();
}
let finalNamespace;
if (is_1.default.string(namespace)) {
finalNamespace = namespace;
}
else if (is_1.default.function_(namespace)) {
finalNamespace = namespace.apply(instance, args);
}
let finalKey;
if (is_1.default.string(key)) {
finalKey = key;
}
else if (is_1.default.function_(key)) {
finalKey = key.apply(instance, args);
}
// istanbul ignore if
if (!finalNamespace || !finalKey) {
return callback();
}
finalKey = `cache-decorator:${finalKey}`;
// prevent concurrent processing and cache writes
const releaseLock = await (0, mutex_1.acquireLock)(finalKey, finalNamespace);
try {
const oldRecord = await packageCache.get(finalNamespace, finalKey);
const ttlValues = (0, ttl_1.resolveTtlValues)(finalNamespace, ttlMinutes);
const softTtl = ttlValues.softTtlMinutes;
const hardTtl = methodName === 'getReleases' || methodName === 'getDigest'
? ttlValues.hardTtlMinutes
: // Skip two-tier TTL for any intermediate data fetching
softTtl;
let oldData;
if (oldRecord) {
const now = luxon_1.DateTime.local();
const cachedAt = luxon_1.DateTime.fromISO(oldRecord.cachedAt);
const softDeadline = cachedAt.plus({ minutes: softTtl });
if (now < softDeadline) {
return oldRecord.value;
}
const hardDeadline = cachedAt.plus({ minutes: hardTtl });
if (now < hardDeadline) {
oldData = oldRecord.value;
}
}
let newData;
if (oldData) {
try {
newData = (await callback());
}
catch (err) {
logger_1.logger.debug({ err }, 'Package cache decorator: callback error, returning old data');
return oldData;
}
}
else {
newData = (await callback());
}
if (!is_1.default.undefined(newData)) {
const newRecord = {
cachedAt: luxon_1.DateTime.local().toISO(),
value: newData,
};
await packageCache.set(finalNamespace, finalKey, newRecord, hardTtl);
}
return newData;
}
finally {
releaseLock();
}
});
}
//# sourceMappingURL=decorator.js.map