import {AsyncCache} from 'utils-decorators'; import * as redis from 'redis'; import {RedisClient} from 'redis'; import {promisify} from 'util'; import * as config from 'config'; export class RedisCache implements AsyncCache { delete: (key: string) => Promise; private readonly client: RedisClient; private readonly clientSet: (key: string, value: string, unit: 'PX', ttl: number) => Promise; private readonly clientGet: (key: string) => Promise; private readonly cacheConf: CacheConf; constructor(cacheConf: CacheConf) { this.cacheConf = { parse: JSON.parse, stringify: JSON.stringify, ...cacheConf, }; const redisConf: RedisConf = config.get('redis'); this.client = redis.createClient({ host: redisConf.host, port: redisConf.port, ...(redisConf.password && {password: redisConf.password}), prefix: cacheConf.name, }); this.clientGet = promisify(this.client.get).bind(this.client); this.clientSet = promisify(this.client.set).bind(this.client); this.delete = promisify(this.client.del).bind(this.client); } async get(key: string): Promise { const strVal = await this.clientGet(key); return strVal !== null ? this.cacheConf.parse(strVal) : null; } set(key: string, value: D): Promise { return this.clientSet(key, this.cacheConf.stringify(value), 'PX', this.cacheConf.ttl); } async has(key: string): Promise { return (await this.get(key)) !== null; } } interface RedisConf { host: string; port: number; password: string; } interface CacheConf { name: string; ttl: number; parse?: (val: string) => D; stringify?: (val: D) => string; }