import { getTenantId } from "../../context" import redis from "../../redis/init" import RedisWrapper from "../../redis" function generateTenantKey(key: string) { const tenantId = getTenantId() return `${key}:${tenantId}` } export = class BaseCache { client: RedisWrapper | undefined constructor(client: RedisWrapper | undefined = undefined) { this.client = client } async getClient() { return !this.client ? await redis.getCacheClient() : this.client } async keys(pattern: string) { const client = await this.getClient() return client.keys(pattern) } /** * Read only from the cache. */ async get(key: string, opts = { useTenancy: true }) { key = opts.useTenancy ? generateTenantKey(key) : key const client = await this.getClient() return client.get(key) } /** * Write to the cache. */ async store( key: string, value: any, ttl: number | null = null, opts = { useTenancy: true } ) { key = opts.useTenancy ? generateTenantKey(key) : key const client = await this.getClient() await client.store(key, value, ttl) } /** * Remove from cache. */ async delete(key: string, opts = { useTenancy: true }) { key = opts.useTenancy ? generateTenantKey(key) : key const client = await this.getClient() return client.delete(key) } /** * Read from the cache. Write to the cache if not exists. */ async withCache( key: string, ttl: number, fetchFn: any, opts = { useTenancy: true } ) { const cachedValue = await this.get(key, opts) if (cachedValue) { return cachedValue } try { const fetchedValue = await fetchFn() await this.store(key, fetchedValue, ttl, opts) return fetchedValue } catch (err) { console.error("Error fetching before cache - ", err) throw err } } async bustCache(key: string, opts = { client: null }) { const client = await this.getClient() try { await client.delete(generateTenantKey(key)) } catch (err) { console.error("Error busting cache - ", err) throw err } } }