UNPKG

renovate

Version:

Automated dependency updates. Flexible so you don't need to be.

118 lines (117 loc) 3.45 kB
import { regEx } from "../../../regex.js"; import { logger } from "../../../../logger/index.js"; import { parseUrl } from "../../../url.js"; import { compressToBase64, decompressFromBase64 } from "../../../compress.js"; import { PackageCacheBase } from "./base.js"; import { DateTime } from "luxon"; import { createClient, createCluster } from "@redis/client"; //#region lib/util/cache/package/impl/redis.ts function normalizeRedisUrl(url) { return url.replace(regEx(/^(rediss?)\+cluster:\/\//), "$1://"); } var PackageCacheRedis = class PackageCacheRedis extends PackageCacheBase { static async create(url, prefix) { const rprefix = prefix ?? ""; logger.debug("Redis cache init"); const rewrittenUrl = normalizeRedisUrl(url); const clusteredMode = rewrittenUrl !== url; const config = { url: rewrittenUrl, socket: { reconnectStrategy: (retries) => Math.min(retries * 100, 3e3) }, pingInterval: 3e4 }; let client; if (clusteredMode) { const clusterConfig = { rootNodes: [config] }; const parsedUrl = parseUrl(rewrittenUrl); if (parsedUrl?.username) clusterConfig.defaults = { username: parsedUrl.username }; if (parsedUrl?.password) { clusterConfig.defaults ??= {}; clusterConfig.defaults.password = parsedUrl.password; } client = createCluster(clusterConfig); } else client = createClient(config); await client.connect(); logger.debug("Redis cache connected"); return new PackageCacheRedis(client, rprefix); } client; rprefix; constructor(client, rprefix) { super(); this.client = client; this.rprefix = rprefix; } getKey(namespace, key) { return `${this.rprefix}${namespace}-${key}`; } async get(namespace, key) { logger.trace(`cache.get(${namespace}, ${key})`); try { const raw = await this.client.get(this.getKey(namespace, key)); if (!raw) return; const cached = JSON.parse(raw); const expiry = DateTime.fromISO(cached.expiry); if (!expiry.isValid || DateTime.local() >= expiry) { await this.rm(namespace, key); return; } logger.trace({ rprefix: this.rprefix, namespace, key }, "Returning cached value"); const json = await decompressFromBase64(cached.value); return JSON.parse(json); } catch { logger.trace({ rprefix: this.rprefix, namespace, key }, "Cache miss"); } } async set(namespace, key, value, hardTtlMinutes) { logger.trace({ rprefix: this.rprefix, namespace, key, hardTtlMinutes }, "Saving cached value"); const ttlSeconds = Math.floor(hardTtlMinutes * 60); try { if (ttlSeconds <= 0) { await this.rm(namespace, key); return; } const compressedValue = await compressToBase64(JSON.stringify(value)); const expiry = DateTime.local().plus({ minutes: hardTtlMinutes }); const payload = JSON.stringify({ value: compressedValue, expiry }); await this.client.set(this.getKey(namespace, key), payload, { EX: ttlSeconds }); } catch (err) { logger.once.warn({ err }, "Error while setting Redis cache value"); } } destroy() { try { this.client.destroy(); } catch (err) { logger.warn({ err }, "Redis cache destroy failed"); } return Promise.resolve(); } async rm(namespace, key) { logger.trace({ rprefix: this.rprefix, namespace, key }, "Removing cache entry"); await this.client.del(this.getKey(namespace, key)); } }; //#endregion export { PackageCacheRedis }; //# sourceMappingURL=redis.js.map