"use strict"; const Moleculer = require("moleculer"), BaseCacher = Moleculer.Cachers.Base; const redisIO = require("ioredis"), //https://github.com/luin/ioredis Promise = require("bluebird"), _ = require("lodash"); import { Redis } from "../drivers/Redis"; export class RedisCacher extends BaseCacher { private client: any; //redis client constructor(opts) { if (typeof opts == "string") opts = { redis_cluster: opts }; super(opts); } init(broker) { super.init(broker); this.client = new Redis(this.opts.redis_cluster); this.client.on("connect", () => { this.logger.info("Services' Redis Cache connected."); }); this.client.on("error", err => { this.logger.error(err); }); this.logger.debug("Services' Cacher created. Prefix: " + this.prefix); } close() { return this.client.quit(); } get(key) { this.logger.debug(`GET ${key}`); return this.client.get(this.prefix + key).then(data => { if (data) { this.logger.debug(`FOUND ${key}`); try { return JSON.parse(data); } catch (err) { this.logger.error("Redis result parse error.", err, data); } } return null; }); } set(key, data, ttl) { data = JSON.stringify(data); this.logger.debug(`SET ${key}`); if (ttl == null) ttl = this.opts.ttl; if (ttl) { return this.client.setex(this.prefix + key, ttl, data); } else { return this.client.set(this.prefix + key, data); } } del(key) { if (_.isArray(key)) { return Promise.all(key.map(m => this.del(m))); } this.logger.debug(`DELETE ${key}`); return this.client.del(this.prefix + key).catch(err => { this.logger.error("Redis `del` error.", key, err); }); } clean(match) { if (_.isArray(match)) { return Promise.all(match.map(m => this.clean(m))); } if (match === undefined || match === null) { //default match = "*"; } if (!_.isString(match)) return new Error("expecting type string, got " + typeof match); return new Promise((resolve, reject) => { match = this.prefix + match.replace(/\*\*/g, "*"); this.logger.debug(`CLEAN ${match}`); let self = this; let scanDel = function(cursor, cb) { self.client.scan(cursor, "MATCH", match, "COUNT", 100, function( err, resp ) { if (err) { return cb(err); } let nextCursor = parseInt(resp[0]); let keys = resp[1]; if (!keys.length) { if (!nextCursor) return cb(null); return scanDel(nextCursor, cb); } self.client.del(keys, function(err) { if (err) { return cb(err); } if (!nextCursor) { return cb(null); } scanDel(nextCursor, cb); }); }); }; scanDel(0, err => { if (err) { this.logger.error("Redis `scanDel` error.", match, err); return reject(err); } resolve(); }); }); } }