diff --git a/packages/api/src/server/index.ts b/packages/api/src/server/index.ts index 0611b037b..4f2a8d3a4 100644 --- a/packages/api/src/server/index.ts +++ b/packages/api/src/server/index.ts @@ -3,6 +3,8 @@ import * as pprof from 'pprof'; import app from './app'; import Bootstrap from './bootstrap'; import Monitoring from './monitoring'; +import RedisWriteClient from '@src/utils/redis/RedisWriteClient'; +import RedisReadClient from '@src/utils/redis/RedisReadClient'; const { API_PORT, @@ -17,6 +19,8 @@ const { AWS_SMTP_USER, AWS_SMTP_PASS, REDIS_URL, + REDIS_URL_WRITE, + REDIS_URL_READ, } = process.env; pprof.heap.start(512 * 1024, 64); @@ -37,11 +41,15 @@ const start = async () => { AWS_SMTP_USER, AWS_SMTP_PASS, REDIS_URL, + REDIS_URL_WRITE, + REDIS_URL_READ, }); Monitoring.init(); await Bootstrap.start(); + await RedisWriteClient.start(); + await RedisReadClient.start(); console.log('[APP] Storages started', { active_quotes: app._quoteCache.getActiveQuotes(), diff --git a/packages/api/src/server/storage/session.ts b/packages/api/src/server/storage/session.ts index 730559b5b..8b8942468 100644 --- a/packages/api/src/server/storage/session.ts +++ b/packages/api/src/server/storage/session.ts @@ -3,6 +3,8 @@ import UserToken from '@src/models/UserToken'; import { Workspace } from '@src/models/Workspace'; import { AuthService } from '@src/modules/auth/services'; import { ISignInResponse } from '@src/modules/auth/types'; +import RedisReadClient from '@src/utils/redis/RedisReadClient'; +import RedisWriteClient from '@src/utils/redis/RedisWriteClient'; import { isPast } from 'date-fns'; import * as redis from 'redis'; @@ -13,51 +15,22 @@ export interface ISession { user: User; } -const REFRESH_TIME = 300 * 1000; // 5 minutes -const REDIS_URL_WRITE = process.env.REDIS_URL_WRITE || 'redis://127.0.0.1:6379'; -const REDIS_URL_READ = process.env.REDIS_URL_READ || 'redis://127.0.0.1:6379'; +const REFRESH_TIME = 60 * 1000; // 5 minutes const PREFIX = 'session'; export class SessionStorage { private redisClientWrite?: redis.RedisClientType; private redisClientRead?: redis.RedisClientType; - protected constructor() { - this.redisClientWrite = redis.createClient({ - url: REDIS_URL_WRITE, - }); - - this.redisClientRead = redis.createClient({ - url: REDIS_URL_READ, - }); - - this.redisClientWrite.connect().catch(e => { - console.error('[REDIS WRITE CONNECT ERROR]', e); - process.exit(1); - }); - - this.redisClientRead.connect().catch(e => { - console.error('[REDIS READ CONNECT ERROR]', e); - process.exit(1); - }); - } + private constructor() {} public async addSession(sessionId: string, session: ISignInResponse) { - await this.redisClientWrite - .set(`${PREFIX}-${sessionId}`, JSON.stringify(session)) - .catch(e => { - console.error( - '[CACHE_SESSIONS_ADD_ERROR]', - e, - `${PREFIX}-${sessionId}`, - JSON.stringify(session), - ); - }); + await RedisWriteClient.set(`${PREFIX}-${sessionId}`, JSON.stringify(session)); } public async getSession(sessionId: string) { let session: ISignInResponse; - const sessionCache = await this.redisClientRead.get(`${PREFIX}-${sessionId}`); + const sessionCache = await RedisReadClient.get(`${PREFIX}-${sessionId}`); if (sessionCache) { session = JSON.parse(sessionCache) as ISignInResponse; @@ -88,14 +61,14 @@ export class SessionStorage { await UserToken.delete({ token: sessionId, }); - await this.redisClientWrite.del([`${PREFIX}-${sessionId}`]); + await RedisWriteClient.del([`${PREFIX}-${sessionId}`]); } // clean experied sessions public async clearExpiredSessions() { const removedTokens = await AuthService.clearExpiredTokens(); if (removedTokens.length > 0) { - await this.redisClientWrite.del(removedTokens.map(t => `${PREFIX}-${t}`)); + await RedisWriteClient.del(removedTokens.map(t => `${PREFIX}-${t}`)); } } diff --git a/packages/api/src/utils/redis/RedisReadClient.ts b/packages/api/src/utils/redis/RedisReadClient.ts new file mode 100644 index 000000000..bd65a7013 --- /dev/null +++ b/packages/api/src/utils/redis/RedisReadClient.ts @@ -0,0 +1,30 @@ +import { RedisClientType, createClient } from 'redis'; + +const REDIS_URL_READ = process.env.REDIS_URL_WRITE || 'redis://127.0.0.1:6379'; + +export default class RedisReadClient { + private static client: RedisClientType; + + private constructor() {} + + static async start() { + if (!RedisReadClient.client) { + RedisReadClient.client = createClient({ url: REDIS_URL_READ }); + + try { + await RedisReadClient.client.connect(); + } catch (e) { + console.error('[REDIS WRITE CONNECT ERROR]', e); + process.exit(1); + } + } + } + + static async get(key: string): Promise { + try { + return await RedisReadClient.client.get(key); + } catch (e) { + console.error('[CACHE_SESSIONS_GET_ERROR]', e, key); + } + } +} diff --git a/packages/api/src/utils/redis/RedisWriteClient.ts b/packages/api/src/utils/redis/RedisWriteClient.ts new file mode 100644 index 000000000..31c9d3b86 --- /dev/null +++ b/packages/api/src/utils/redis/RedisWriteClient.ts @@ -0,0 +1,38 @@ +import { RedisClientType, createClient } from 'redis'; + +const REDIS_URL_WRITE = process.env.REDIS_URL_WRITE || 'redis://127.0.0.1:6379'; + +export default class RedisWriteClient { + private static client: RedisClientType; + + private constructor() {} + + static async start() { + if (!RedisWriteClient.client) { + RedisWriteClient.client = createClient({ url: REDIS_URL_WRITE }); + + try { + await RedisWriteClient.client.connect(); + } catch (e) { + console.error('[REDIS WRITE CONNECT ERROR]', e); + process.exit(1); + } + } + } + + static async set(key: string, value: string) { + try { + await RedisWriteClient.client.set(key, value); + } catch (e) { + console.error('[CACHE_SESSIONS_ADD_ERROR]', e, key, value); + } + } + + static async del(keys: string[]) { + try { + await RedisWriteClient.client.del(keys); + } catch (e) { + console.error('[CACHE_SESSIONS_REMOVE_ERROR]', e, keys); + } + } +}