@imqueue/rpc
Version:
RPC-like client-service implementation over messaging queue
163 lines • 5.4 kB
JavaScript
;
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