UNPKG

@trifrost/core

Version:

Blazingly fast, runtime-agnostic server framework for modern edge and node environments

77 lines (76 loc) 2.05 kB
import { split } from '@valkyriestudios/utils/array'; import { TriFrostCache } from '../modules/Cache/_Cache'; import { TriFrostRateLimit } from '../modules/RateLimit/_RateLimit'; import { Store } from './_Storage'; /** * MARK: Adapter */ export class RedisStoreAdapter { #redis; constructor(redis) { this.#redis = redis; } async get(key) { const val = await this.#redis.get(key); if (!val) return null; return JSON.parse(val); } async set(key, value, ttl) { await this.#redis.set(key, JSON.stringify(value), 'EX', ttl); } async del(key) { await this.#redis.del(key); } async delPrefixed(prefix) { let cursor = '0'; const acc = new Set(); do { const [next, keys] = await this.#redis.scan(cursor, 'MATCH', prefix + '*', 'COUNT', 250); cursor = next; for (let i = 0; i < keys.length; i++) acc.add(keys[i]); } while (cursor && cursor !== '0'); if (!acc.size) return; for (const batch of split([...acc], 100)) { await this.#redis.del(...batch); } } async stop() { /* Nothing to do here */ } } /** * MARK: Store */ export class RedisStore extends Store { constructor(redis) { super('RedisStore', new RedisStoreAdapter(redis)); } } /** * MARK: Cache */ export class RedisCache extends TriFrostCache { constructor(cfg) { if (!cfg?.store) throw new Error('RedisCache: Expected a store initializer'); super({ store: new Store('RedisCache', new RedisStoreAdapter(cfg.store)), }); } } /** * MARK: RateLimit */ export class RedisRateLimit extends TriFrostRateLimit { constructor(cfg) { if (!cfg?.store) throw new Error('RedisRateLimit: Expected a store initializer'); super({ ...cfg, store: new Store('RedisRateLimit', new RedisStoreAdapter(cfg.store)), }); } }