diff --git a/integrations/sample-app/app/console/cache.ts b/integrations/sample-app/app/console/cache.ts index 8ccc18a..910ab2a 100644 --- a/integrations/sample-app/app/console/cache.ts +++ b/integrations/sample-app/app/console/cache.ts @@ -7,7 +7,7 @@ export class TestCacheConsoleCommand { const strValue = 'Hello world!'; const objValue = { msg: 'Hey there!' }; - const disks = ['memory', 'redis']; + const disks = ['memory', 'redis', 'dicedb']; for (const disk of disks) { _cli.info(`Testing integration for ${disk} cache`); /** diff --git a/integrations/sample-app/config/cache.ts b/integrations/sample-app/config/cache.ts index 1092ec5..c40b95f 100644 --- a/integrations/sample-app/config/cache.ts +++ b/integrations/sample-app/config/cache.ts @@ -40,6 +40,15 @@ export default configNamespace( database: +process.env.REDIS_DB || 0, prefix: 'intentjs', }, + + dicedb: { + driver: 'dicedb', + host: process.env.DICEDB_HOST || '127.0.0.1', + password: process.env.DICEDB_PASSWORD || undefined, + port: +process.env.DICEDB_PORT || 6379, + database: +process.env.DICEDB_DB || 0, + prefix: 'intentjs', + }, }, }), ); diff --git a/packages/core/lib/cache/drivers/dice-db.ts b/packages/core/lib/cache/drivers/dice-db.ts new file mode 100644 index 0000000..da21dfd --- /dev/null +++ b/packages/core/lib/cache/drivers/dice-db.ts @@ -0,0 +1,96 @@ +import { GenericFunction } from '../../interfaces'; +import { Package } from '../../utils'; +import { CacheDriver, RedisDriverOption } from '../interfaces'; +import IORedis from 'ioredis'; + +export class DiceDbDriver implements CacheDriver { + private client: any; + + constructor(private options: RedisDriverOption) { + // const IORedis = Package.load('ioredis'); + if (options.url) { + this.client = new IORedis(options.url, { + db: options.database || 0, + enableReadyCheck: false, + }); + } else { + this.client = new IORedis({ + host: options.host, + port: options.port, + username: options.username, + password: options.password, + db: options.database, + enableReadyCheck: false, + }); + } + } + + async get(key: string): Promise { + const value = await this.client.get(`${this.options.prefix}:::${key}`); + if (!value) return null; + try { + return JSON.parse(value); + } catch (e) { + return value; + } + } + + async set( + key: string, + value: string | number | Record, + ttlInSec?: number, + ): Promise { + try { + const redisKey = `${this.options.prefix}:::${key}`; + ttlInSec + ? await this.client.set(redisKey, JSON.stringify(value), 'EX', ttlInSec) + : await this.client.set(redisKey, JSON.stringify(value)); + return true; + } catch { + return false; + } + } + + async has(key: string): Promise { + const num = await this.client.exists(`${this.options.prefix}:::${key}`); + return !!num; + } + + async remember( + key: string, + cb: GenericFunction, + ttlInSec: number, + ): Promise { + const value = await this.get(key); + if (value) return value; + const response = await cb(); + if (response) await this.set(key, response, ttlInSec); + + return response; + } + + async rememberForever(key: string, cb: GenericFunction): Promise { + const value = await this.get(key); + if (value) return value; + const response = await cb(); + if (response) await this.set(key, response); + return response; + } + + async forget(key: string): Promise { + try { + await this.client.del(this.storeKey(key)); + return true; + } catch (e) { + return false; + } + } + + private storeKey(key: string): string { + return `${this.options.prefix}:::${key}`; + } + + getClient(): T { + return this.client as unknown as T; + } +} diff --git a/packages/core/lib/cache/interfaces/options.ts b/packages/core/lib/cache/interfaces/options.ts index 5ce268c..53c3773 100644 --- a/packages/core/lib/cache/interfaces/options.ts +++ b/packages/core/lib/cache/interfaces/options.ts @@ -11,6 +11,17 @@ export interface RedisDriverOption { prefix?: string; } +export interface DiceDbDriverOption { + driver: 'dicedb'; + host?: string; + port?: number; + url?: string; + username?: string; + password?: string; + database?: number; + prefix?: string; +} + export interface InMemoryDriverOption { driver: 'memory'; prefix: string; @@ -20,7 +31,10 @@ export interface CacheOptions { isGlobal?: boolean; default: string; stores: { - [key: string]: RedisDriverOption | InMemoryDriverOption; + [key: string]: + | RedisDriverOption + | InMemoryDriverOption + | DiceDbDriverOption; }; } diff --git a/packages/core/lib/cache/service.ts b/packages/core/lib/cache/service.ts index 2d0a664..2802264 100644 --- a/packages/core/lib/cache/service.ts +++ b/packages/core/lib/cache/service.ts @@ -6,10 +6,15 @@ import { InMemoryDriverOption, RedisDriverOption, } from './interfaces'; +import { DiceDbDriver } from './drivers/dice-db'; @Injectable() export class CacheService { - static driverMap = { redis: RedisDriver, memory: InMemoryDriver }; + static driverMap = { + redis: RedisDriver, + memory: InMemoryDriver, + dicedb: DiceDbDriver, + }; static stores = new Map(); constructor() {}