UNPKG

renovate

Version:

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

121 lines 4.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SqlitePackageCache = void 0; const tslib_1 = require("tslib"); const node_util_1 = require("node:util"); const node_zlib_1 = tslib_1.__importStar(require("node:zlib")); const fs_extra_1 = require("fs-extra"); const upath = tslib_1.__importStar(require("upath")); const expose_cjs_1 = require("../../../expose.cjs"); const logger_1 = require("../../../logger"); const fs_1 = require("../../fs"); const brotliCompress = (0, node_util_1.promisify)(node_zlib_1.default.brotliCompress); const brotliDecompress = (0, node_util_1.promisify)(node_zlib_1.default.brotliDecompress); function compress(input) { const jsonStr = JSON.stringify(input); return brotliCompress(jsonStr, { params: { [node_zlib_1.constants.BROTLI_PARAM_MODE]: node_zlib_1.constants.BROTLI_MODE_TEXT, [node_zlib_1.constants.BROTLI_PARAM_QUALITY]: 3, }, }); } async function decompress(input) { const buf = await brotliDecompress(input); const jsonStr = buf.toString('utf8'); return JSON.parse(jsonStr); } class SqlitePackageCache { client; upsertStatement; getStatement; deleteExpiredRows; countStatement; static async init(cacheDir) { // simply let it throw if it fails, so no test coverage needed const Sqlite = (0, expose_cjs_1.sqlite)(); const sqliteDir = upath.join(cacheDir, 'renovate/renovate-cache-sqlite'); await (0, fs_1.ensureDir)(sqliteDir); const sqliteFile = upath.join(sqliteDir, 'db.sqlite'); if (await (0, fs_extra_1.exists)(sqliteFile)) { logger_1.logger.debug(`Using SQLite package cache: ${sqliteFile}`); } else { logger_1.logger.debug(`Creating SQLite package cache: ${sqliteFile}`); } const client = new Sqlite(sqliteFile); const res = new SqlitePackageCache(client); return res; } constructor(client) { this.client = client; client.pragma('journal_mode = WAL'); client.pragma("encoding = 'UTF-8'"); client .prepare(` CREATE TABLE IF NOT EXISTS package_cache ( namespace TEXT NOT NULL, key TEXT NOT NULL, expiry INTEGER NOT NULL, data BLOB NOT NULL, PRIMARY KEY (namespace, key) ) `) .run(); client .prepare('CREATE INDEX IF NOT EXISTS expiry ON package_cache (expiry)') .run(); client .prepare('CREATE INDEX IF NOT EXISTS namespace_key ON package_cache (namespace, key)') .run(); this.upsertStatement = client.prepare(` INSERT INTO package_cache (namespace, key, data, expiry) VALUES (@namespace, @key, @data, unixepoch() + @ttlSeconds) ON CONFLICT (namespace, key) DO UPDATE SET data = @data, expiry = unixepoch() + @ttlSeconds `); this.getStatement = client .prepare(` SELECT data FROM package_cache WHERE namespace = @namespace AND key = @key AND expiry > unixepoch() `) .pluck(true); this.deleteExpiredRows = client.prepare(` DELETE FROM package_cache WHERE expiry <= unixepoch() `); this.countStatement = client .prepare('SELECT COUNT(*) FROM package_cache') .pluck(true); } async set(namespace, key, value, ttlMinutes = 5) { const data = await compress(value); const ttlSeconds = ttlMinutes * 60; this.upsertStatement.run({ namespace, key, data, ttlSeconds }); return Promise.resolve(); } async get(namespace, key) { const data = this.getStatement.get({ namespace, key }); if (!data) { return undefined; } return await decompress(data); } cleanupExpired() { const start = Date.now(); const totalCount = this.countStatement.get(); const { changes: deletedCount } = this.deleteExpiredRows.run(); const finish = Date.now(); const durationMs = finish - start; logger_1.logger.debug(`SQLite package cache: deleted ${deletedCount} of ${totalCount} entries in ${durationMs}ms`); } cleanup() { this.cleanupExpired(); this.client.close(); return Promise.resolve(); } } exports.SqlitePackageCache = SqlitePackageCache; //# sourceMappingURL=sqlite.js.map