UNPKG

ltcache

Version:

A lightweight, in-memory caching library - like Redis but much simpler. Features TTL support, concurrent request handling, and comprehensive statistics. Perfect for Node.js applications that need fast caching without the complexity of Redis.

102 lines 3.24 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.cache = void 0; /* eslint-disable max-lines-per-function */ const logger_1 = require("./logger"); function cache(debug = false) { const cache = new Map(); const clearTimeouts = new Map(); const pendingGets = new Map(); let hits = 0; let misses = 0; const set = (key, value, lifetimeInSeconds) => { cache.set(key, value); debug && logger_1.logger.debug(`set: ${key}`); if (clearTimeouts.has(key)) clearTimeout(clearTimeouts.get(key)); if (lifetimeInSeconds && lifetimeInSeconds > 0) { clearTimeouts.set(key, setTimeout(() => { cache.delete(key); clearTimeouts.delete(key); }, lifetimeInSeconds * 1000)); } }; const get = async (key, fn, lifetimeInSeconds) => { if (cache.has(key)) { hits++; debug && logger_1.logger.debug(`hit: ${key}`); return cache.get(key); } misses++; debug && logger_1.logger.debug(`miss: ${key}`); if (typeof fn === 'function') { // Check if there's already a pending request for this key if (pendingGets.has(key)) { debug && logger_1.logger.debug(`waiting for pending request: ${key}`); return pendingGets.get(key); } // Create a new pending request const pendingPromise = (async () => { try { const value = await fn(); set(key, value, lifetimeInSeconds); return value; } finally { pendingGets.delete(key); } })(); pendingGets.set(key, pendingPromise); return pendingPromise; } return cache.get(key); }; const remove = (key) => { if (key instanceof RegExp) { for (const [k] of cache) { if (key.test(k)) { cache.delete(k); pendingGets.delete(k); } } } else { cache.delete(key); pendingGets.delete(key); } }; const reset = () => { cache.clear(); pendingGets.clear(); hits = 0; misses = 0; }; const getSizeKb = () => { let totalSize = 0; for (const [key, value] of cache) { // Estimate size of key and value const keySize = new Blob([key]).size; const valueSize = new Blob([JSON.stringify(value)]).size; totalSize += keySize + valueSize; } return Math.round(totalSize / 1024); }; const report = () => { const totalRequests = hits + misses; const hitRate = totalRequests > 0 ? (hits / totalRequests) * 100 : 0; return { numItems: cache.size, hitRate: Math.round(hitRate * 100) / 100, sizeKb: getSizeKb(), }; }; return { get, set, remove, reset, report, }; } exports.cache = cache; //# sourceMappingURL=cache.js.map