UNPKG

@nhan2804/nestjs-cacheable

Version:

@nestjs/cacheable is a flexible caching library for NestJS that leverages Redis for efficient and scalable storage. With support for function-level caching through easy-to-use decorators, it allows developers to seamlessly enhance performance while mainta

85 lines (84 loc) 3.73 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Cacheable = Cacheable; const cacheable_helpers_1 = require("./cacheable.helpers"); const log = (m) => { if (cacheable_helpers_1.cacheConfigOption.isDev) { console.log(m); } }; function Cacheable(options) { return (target, propertyKey, descriptor) => { const originalMethod = descriptor.value; descriptor.value = async function (...args) { const { ttl, refreshThreshold, key, prefix, type, concatArgs = true, } = Object.assign(Object.assign({}, cacheable_helpers_1.cacheConfigOption), options); const cacheManager = (0, cacheable_helpers_1.getCacheManager)(); const initKey = `${target.constructor.name}-${propertyKey.toString()}-${args .map((arg) => (typeof arg === "object" ? JSON.stringify(arg) : arg)) .join("-")}`; let cacheKey = initKey; log({ ttl, refreshThreshold, key, prefix, type, concatArgs, }); if (typeof key === "string") { cacheKey = key; if (concatArgs) { cacheKey = `${key}-${initKey}`; } } else if (typeof key === "function") { cacheKey = key(args); } if (!cacheKey) { throw new Error("cacheKey can not be empty!"); } log("key " + cacheKey); const currentTime = Date.now(); if (type === "delete") { log(`Deleting cache for key: ${cacheKey}`); await cacheManager.del(cacheKey); if (prefix) { const allKeys = await cacheManager.store.keys(); const prefixKeys = allKeys.filter((key) => key.startsWith(prefix)); for (const key of prefixKeys) { await cacheManager.del(key); log(`Deleted cache for key with prefix: ${key}`); } } const newValue = await originalMethod.apply(this, args); await cacheManager.set(cacheKey, { value: newValue, timestamp: currentTime }, ttl); return newValue; } if (type === "bust") { log(`Force refresh cache for key: ${cacheKey}`); const newValue = await originalMethod.apply(this, args); await cacheManager.set(cacheKey, { value: newValue, timestamp: currentTime }, ttl); return newValue; } const cachedData = await cacheManager.get(cacheKey); if (cachedData) { const { value, timestamp } = cachedData; const elapsed = (currentTime - timestamp) / 1000; const throttleTime = ttl * (refreshThreshold || elapsed); if (elapsed >= throttleTime) { log(`Auto-refresh cache for key: ${cacheKey}`); const newValue = await originalMethod.apply(this, args); await cacheManager.set(cacheKey, { value: newValue, timestamp: currentTime }, ttl); return newValue; } log(`Cache hit for key: ${cacheKey}`); return value; } log(`Cache miss for key: ${cacheKey}`); const result = await originalMethod.apply(this, args); await cacheManager.set(cacheKey, { value: result, timestamp: currentTime }, ttl); return result; }; return descriptor; }; }