swaf/src/components/RedisComponent.ts

101 lines
3.1 KiB
TypeScript

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<void> {
this.redisClient = redis.createClient(config.get('redis.port'), config.get('redis.host'), {
password: config.has('redis.password') ? config.get<string>('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<string>('redis.prefix') + '-session:',
});
}
public async stop(): Promise<void> {
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<T extends string | undefined>(key: string, defaultValue?: T): Promise<T> {
return await new Promise<T>((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<boolean> {
return await this.get(key) !== undefined;
}
public async forget(key: string): Promise<void> {
return await new Promise<void>((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<void> {
return await new Promise<void>((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();
});
});
}
}