UNPKG

adonis5-cache

Version:
152 lines (151 loc) 6.13 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const DefaultCacheContext_1 = __importDefault(require("./CacheContexts/DefaultCacheContext")); const CacheEventEmitter_1 = __importDefault(require("./CacheEventEmitter")); const ramda_1 = require("ramda"); const TaggableCacheManager_1 = __importDefault(require("./TaggableCacheManager")); const TypeGuards_1 = require("./TypeGuards"); const ms_1 = __importDefault(require("ms")); class CacheManager { constructor({ config, eventEmitter }) { this.cacheStorages = {}; this.cacheContexts = {}; this.tempContextName = null; this.tempStorageName = null; this.cacheTags = []; this.cacheConfig = config; this.eventEmitter = new CacheEventEmitter_1.default(this.cacheConfig.enabledEvents, eventEmitter); this.currentCacheStorageName = this.cacheConfig.currentCacheStorage; this.initCacheContexts(); } get recordTTL() { return this.cacheConfig.recordTTL || CacheManager.DEFAULT_RECORD_TTL; } get recordKeyPrefix() { return this.cacheConfig.cacheKeyPrefix; } get context() { return this.tempContextName ? this.cacheContexts[this.tempContextName] : this.cacheContexts[this.currentCacheContextName]; } get storage() { return this.tempStorageName !== null ? this.cacheStorages[this.tempStorageName] : this.cacheStorages[this.currentCacheStorageName]; } registerStorage(storageName, storage) { this.cacheStorages[storageName] = storage; return this; } registerContext(contextName, context) { this.cacheContexts[contextName] = context; return this; } viaContext(contextName) { if (!this.cacheContexts.hasOwnProperty(contextName)) { throw new Error('Unregistered context for Adonis-Cache'); } this.tempContextName = contextName; return this; } viaStorage(storageName) { if (!this.cacheStorages.hasOwnProperty(storageName)) { throw new Error('Unregistered storage for Adonis-Cache'); } this.tempStorageName = storageName; return this; } tags(...tags) { return new TaggableCacheManager_1.default(this, tags); } enableStorage(storageName) { if (!this.cacheStorages.hasOwnProperty(storageName)) { throw new Error('Unregistered storage for Adonis-Cache'); } this.currentCacheStorageName = storageName; return this; } enableContext(contextName) { if (!this.cacheContexts.hasOwnProperty(contextName)) { throw new Error('Unregistered context for Adonis-Cache'); } this.currentCacheContextName = contextName; return this; } async get(key, fallback, ttl) { const cacheValue = await this.storage.get(this.context, this.buildRecordKey(key)); this.emitEventsOnReadOperations({ [key]: cacheValue }); this.restoreState(); return ramda_1.isNil(cacheValue) && fallback ? await this.resolveFallback(key, fallback, this.resolveCacheTTL(ttl)) : cacheValue; } async getMany(keys) { const cachedValues = await this.storage.getMany(this.context, keys.map((key) => this.buildRecordKey(key))); this.emitEventsOnReadOperations(ramda_1.zipObj(keys, cachedValues)); this.restoreState(); return cachedValues; } async put(key, value, ttl) { const operationResult = await this.storage.put(this.context, this.buildRecordKey(key), value, this.resolveCacheTTL(ttl)); this.eventEmitter.emitEvent('cache-record:written', { [key]: value }); this.restoreState(); return operationResult; } async putMany(cacheDictionary, ttl) { const operationResult = await this.storage.putMany(this.context, Object.entries(cacheDictionary).reduce((acc, [key, value]) => { return { ...acc, [this.buildRecordKey(key)]: value }; }, {}), this.resolveCacheTTL(ttl)); this.eventEmitter.emitEvent('cache-record:written', cacheDictionary); this.restoreState(); return operationResult; } async flush() { await this.storage.flush(); } async forget(key) { const result = await this.storage.forget(this.buildRecordKey(key)); this.eventEmitter.emitEvent('cache-record:forgotten', { [key]: result }); return result; } buildRecordKey(userKey) { return this.recordKeyPrefix + userKey; } restoreState() { this.tempStorageName = null; this.tempContextName = null; this.cacheTags = []; } emitEventsOnReadOperations(cacheData) { const missedKeys = []; const storedData = {}; for (const [key, value] of Object.entries(cacheData)) { value === null ? missedKeys.push(key) : Object.assign(storedData, { [key]: value }); } if (missedKeys.length > 0) { this.eventEmitter.emitEvent('cache-record:missed', { keys: missedKeys }); } if (Object.keys(storedData).length > 0) { this.eventEmitter.emitEvent('cache-record:read', storedData); } } initCacheContexts() { this.currentCacheContextName = 'DEFAULT'; this.cacheContexts = { [this.currentCacheContextName]: DefaultCacheContext_1.default }; } async resolveFallback(key, fallback, ttl) { const fallbackValue = TypeGuards_1.isFunction(fallback) ? await fallback() : fallback; await this.put(key, fallbackValue, this.resolveCacheTTL(ttl)); return fallbackValue; } resolveCacheTTL(ttl) { const ttlInMilliseconds = Number(ms_1.default((ttl || this.recordTTL) + this.cacheConfig.ttlUnits)); return this.storage.resolveTtl(ttlInMilliseconds); } } exports.default = CacheManager; CacheManager.DEFAULT_RECORD_TTL = 6000;