UNPKG

@appolo/cache

Version:
224 lines 8.09 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Cache = void 0; const tslib_1 = require("tslib"); const inject_1 = require("@appolo/inject"); const appolo_cache_1 = require("appolo-cache"); const utils_1 = require("@appolo/utils"); const ResultSymbol = "@result"; let Cache = class Cache { constructor(_options, _valueFn, _scope) { this._options = _options; this._valueFn = _valueFn; this._scope = _scope; this._intervals = new Map(); this._promiseCache = new Map(); } initialize() { this._cache = new appolo_cache_1.Cache(this._options); this._options.getMethod = this._options.peek ? "peek" : "get"; if (this._options.refresh) { this._options.getMethod = this._options.peek ? "peekByExpire" : "getByExpire"; } } get(...args) { let key = this._getKey(args); if (this._options.interval && !this._intervals.get(key)) { let interval = setInterval(this._refreshValue.bind(this, args, key), this._options.interval); this._intervals.set(key, interval); } return this._options.db ? this.getAsyncWithRedis(args, key) : this._getSync(args, key); } async del(...args) { let key = this._getKey(args); this._cache.del(key); if (this._options.db) { let redisKey = this._getRedisKey(key); await this.getRedisProvider().del(redisKey); } } getRedisProvider() { return this.moduleOptions.redisProviderId ? this.injector.get(this.moduleOptions.redisProviderId) : this.redisProvider; } set(value, ...args) { let key = this._getKey(args); this._setMemoryValue(key, value); if (this._options.db) { return this._setRedisValue(key, value); } } _getSync(args, key) { let item = this._getValueFromMemory(args, key); if (this._isValidItem(item)) { return this._options.isPromise ? Promise.resolve(item[ResultSymbol]) : item[ResultSymbol]; } let result = this._getValue(args, key); return result; } _isValidItem(item) { if (!item || !item.hasOwnProperty || !item.hasOwnProperty(ResultSymbol)) { return false; } if (this._options.cacheNull) { return true; } let value = item[ResultSymbol]; return value !== null && value !== undefined; } async getAsyncWithRedis(args, key) { let item = null; if (this._options.memory) { item = this._getValueFromMemory(args, key); if (this._isValidItem(item)) { return item[ResultSymbol]; } } item = await this._getValueFromRedis(args, key); if (this._isValidItem(item)) { return item[ResultSymbol]; } let result = this._getValue(args, key); return result; } _getKey(args) { if (this._options.resolver) { return this._options.resolver.apply(this._scope, args); } if (this._options.multi) { return JSON.stringify(args); } let arg = args[0] || ""; return typeof arg == "object" ? JSON.stringify(arg) : arg; } _getValueFromMemory(args, key) { let result = this._cache[this._options.getMethod](key, this._getMemoryMaxAge(), this._options.refreshTime); if (!result) { return null; } let value = this._needRefresh(result, args, key, !this._options.db); if (this._options.db && this._options.refresh && !result.validExpire) { this._getValueFromRedis(args, key).catch(e => this.logger.error(`failed to set redis cache ${key}`, { e })); } return this._options.clone ? JSON.parse(value) : value; } async _getValueFromRedis(args, key) { let redisKey = this._getRedisKey(key); let result; try { result = await (this._options.refresh && this._options.maxAge ? this.getRedisProvider().getByExpire(redisKey, this._getRedisMaxAge(), this._options.refreshTime) : this.getRedisProvider().get(redisKey)); } catch (e) { this.logger.error(`failed to get redis cache ${key}`, { e }); } if (!result) { return null; } let value = this._needRefresh(result, args, key); this._setMemoryValue(key, value); return value; } _needRefresh(result, args, key, refresh = true) { if (!this._options.refresh) { return result; } let value = result.value; if (!result.validExpire && refresh) { this._options.randomRefresh ? setTimeout(() => this._refreshValue(args, key), utils_1.Numbers.random(this._options.randomRefresh)) : this._refreshValue(args, key); } return value; } _getRedisMaxAge() { let age = (this._options.dbMaxAge || this._options.maxAge); age = Math.floor(age / 1000); return age; } _getMemoryMaxAge() { let age = this._options.maxAge; return age; } _getRedisKey(key) { if (typeof key != "string") { key = JSON.stringify(key); } key = key || ""; if (this._options.dbKeyPrefix) { key = `${this._options.dbKeyPrefix}:${key}`; } return key; } _getValue(args, key) { if (!this._valueFn) { return null; } let promiseCached = this._promiseCache.get(key); if (promiseCached) { return promiseCached; } let result = this._valueFn.apply(this._scope, args); if (!result || !result.then || !result.catch) { this._setMemoryValue(key, result); return result; } this._options.isPromise = true; let value = result.then((data) => { this._setMemoryValue(key, data); this._setRedisValue(key, data); this._promiseCache.delete(key); return data; }).catch((e) => { this._promiseCache.delete(key); throw e; }); this._promiseCache.set(key, value); return value; } _setMemoryValue(key, value) { if (!this._options.memory) { return; } let dto = value && value.hasOwnProperty && value.hasOwnProperty(ResultSymbol) ? value : { [ResultSymbol]: value }; this._cache.set(key, this._options.clone ? JSON.stringify(dto) : dto, this._getMemoryMaxAge()); } _setRedisValue(key, value) { if (!this._options.db) { return; } let redisKey = this._getRedisKey(key), age = this._getRedisMaxAge(); let dto = value && value.hasOwnProperty && value.hasOwnProperty(ResultSymbol) ? value : { [ResultSymbol]: value }; return ((this._options.maxAge || this._options.dbMaxAge) ? this.getRedisProvider().setWithExpire(redisKey, dto, age) : this.getRedisProvider().set(redisKey, dto)) .catch(e => this.logger.error(`failed to set redis cache ${key}`, { e })); } _refreshValue(args, key) { let value = this._getValue(args, key); Promise.resolve(value).catch((e) => this.logger.error(`failed to refresh cache ${key}`, { e })); } get cache() { return this._cache; } }; tslib_1.__decorate([ (0, inject_1.lazy)() ], Cache.prototype, "redisProvider", void 0); tslib_1.__decorate([ (0, inject_1.inject)() ], Cache.prototype, "moduleOptions", void 0); tslib_1.__decorate([ (0, inject_1.inject)() ], Cache.prototype, "logger", void 0); tslib_1.__decorate([ (0, inject_1.inject)() ], Cache.prototype, "injector", void 0); tslib_1.__decorate([ (0, inject_1.init)() ], Cache.prototype, "initialize", null); Cache = tslib_1.__decorate([ (0, inject_1.define)() ], Cache); exports.Cache = Cache; //# sourceMappingURL=cache.js.map