UNPKG

@imqueue/rpc

Version:

RPC-like client-service implementation over messaging queue

163 lines 5.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RedisCache = exports.REDIS_CLIENT_INIT_ERROR = exports.DEFAULT_REDIS_CACHE_OPTIONS = void 0; const core_1 = require("@imqueue/core"); const os = require("os"); exports.DEFAULT_REDIS_CACHE_OPTIONS = Object.assign(Object.assign({}, core_1.DEFAULT_IMQ_OPTIONS), { prefix: 'imq-cache' }); exports.REDIS_CLIENT_INIT_ERROR = 'Redis client is not initialized!'; /** * Class RedisCache. Implements cache engine over redis. */ class RedisCache { constructor() { this.name = RedisCache.name; this.ready = false; } /** * Initializes cache instance * * @param {IRedisCacheOptions} [options] * @returns {Promise<RedisCache>} */ async init(options) { this.options = Object.assign(Object.assign({}, exports.DEFAULT_REDIS_CACHE_OPTIONS), options); this.logger = this.options.logger || // istanbul ignore next console; if (RedisCache.redis) { return this; } if (this.options.conn) { this.logger.info('Re-using given connection for cache.'); RedisCache.redis = this.options.conn; return this; } return new Promise((resolve, reject) => { const connectionName = `${this.options.prefix}:${this.name}:pid:${process.pid}:host:${os.hostname()}`; RedisCache.redis = new core_1.Redis({ port: Number(this.options.port), host: String(this.options.host), username: this.options.username, password: this.options.password, connectionName, }); RedisCache.redis.on('ready', async () => { this.logger.info('%s: redis cache connected, host %s:%s, pid %s', this.name, this.options.host, this.options.port, process.pid); this.ready = true; resolve(this); }); // istanbul ignore next RedisCache.redis.on('error', (err) => { this.logger.error(`${this.name}: error connecting redis, pid ${process.pid}:`, err); reject(err); }); }); } /** * Returns fully qualified key name for a given generic key * * @access private * @param {string} key * @returns {string} */ key(key) { return `${this.options.prefix}:${this.name}:${key}`; } /** * Returns value stored in cache by a given key * * @param {string} key * @returns {Promise<any>} */ async get(key) { if (!RedisCache.redis) { throw new TypeError(exports.REDIS_CLIENT_INIT_ERROR); } // noinspection ES6RedundantAwait const data = await RedisCache.redis.get(this.key(key)); if (data) { return JSON.parse(data); } return undefined; } /** * Stores in cache given value under given key. If TTL is specified, * cached value will expire in a given number of milliseconds. If NX * argument set to true will create key:value in cache only if it does * not exist yet. Given value could be any JSON-compatible object and * will be serialized automatically. * * @param {string} key * @param {any} value * @param {number} ttl * @param {boolean} nx * @returns {Promise<boolean>} */ async set(key, value, ttl, nx = false) { if (!RedisCache.redis) { throw new TypeError(exports.REDIS_CLIENT_INIT_ERROR); } const args = [ this.key(key), JSON.stringify(value && value.then ? await value : value) ]; if (ttl && ttl > 0) { args.push('PX', ttl); } if (nx) { args.push('NX'); } return await RedisCache.redis.set.apply(RedisCache.redis, args); } /** * Removes stored in cache value under given key * * @param {string} key * @returns {Promise<boolean>} */ async del(key) { if (!RedisCache.redis) { throw new TypeError(exports.REDIS_CLIENT_INIT_ERROR); } return !!await RedisCache.redis.del(this.key(key)); } /** * Purges all keys from cache by a given wildcard mask * * @param {string} keyMask * @return {boolean} */ async purge(keyMask) { if (!RedisCache.redis) { throw new TypeError(exports.REDIS_CLIENT_INIT_ERROR); } try { // noinspection SpellCheckingInspection await RedisCache.redis.eval(`for _,k in ipairs(redis.call('keys','${keyMask}')) do redis.call('del',k) end`, 0); return true; } catch (e) { this.logger.error(e); return false; } } /** * Safely destroys redis connection * * @returns {Promise<void>} */ static async destroy() { try { // istanbul ignore else if (RedisCache.redis) { RedisCache.redis.removeAllListeners(); RedisCache.redis.disconnect(false); RedisCache.redis.quit(); delete RedisCache.redis; } } catch (err) { } } } exports.RedisCache = RedisCache; //# sourceMappingURL=RedisCache.js.map