import ApplicationComponent from "../ApplicationComponent"; import {Express} from "express"; import redis, {RedisClient} from "redis"; import config from "config"; import {logger} from "../Logger"; import session, {Store} from "express-session"; import connect_redis from "connect-redis"; import CacheProvider from "../CacheProvider"; const RedisStore = connect_redis(session); export default class RedisComponent extends ApplicationComponent implements CacheProvider { private redisClient?: RedisClient; private store?: Store; public async start(_app: Express): Promise { this.redisClient = redis.createClient(config.get('redis.port'), config.get('redis.host'), { password: config.has('redis.password') ? config.get('redis.password') : undefined, }); this.redisClient.on('error', (err: Error) => { logger.error(err, 'An error occurred with redis.'); }); this.store = new RedisStore({ client: this.redisClient, prefix: config.get('redis.prefix') + '-session:', }); } public async stop(): Promise { const redisClient = this.redisClient; if (redisClient) { await this.close('Redis connection', callback => redisClient.quit(callback)); } } public getStore(): Store { if (!this.store) throw `Redis store was not initialized.`; return this.store; } public canServe(): boolean { return this.redisClient !== undefined && this.redisClient.connected; } public async get(key: string, defaultValue?: T): Promise { return await new Promise((resolve, reject) => { if (!this.redisClient) { reject(`Redis store was not initialized.`); return; } this.redisClient.get(key, (err, val) => { if (err) { reject(err); return; } resolve((val || defaultValue || undefined) as T); }); }); } public async has(key: string): Promise { return await this.get(key) !== undefined; } public async forget(key: string): Promise { return await new Promise((resolve, reject) => { if (!this.redisClient) { reject(`Redis store was not initialized.`); return; } this.redisClient.del(key, (err) => { if (err) { reject(err); return; } resolve(); }); }); } public async remember(key: string, value: string, ttl: number): Promise { return await new Promise((resolve, reject) => { if (!this.redisClient) { reject(`Redis store was not initialized.`); return; } this.redisClient.psetex(key, ttl, value, (err) => { if (err) { reject(err); return; } resolve(); }); }); } }