import type { FeedDependencies } from "./feeds.dependencies.js"; /** TTL-faithful Redis surface, including ownership checks for renewable leases. */ type FeedRedis = FeedDependencies["redis"]; export class MemoryFeedRedis implements FeedRedis { readonly entries = new Map(); async get(key: string): Promise { const entry = this.entries.get(key); if (!entry || entry.expiresAt <= Date.now()) { this.entries.delete(key); return null; } return entry.value; } async set(key: string, value: string, options: { nx?: boolean; pxMs?: number } = {}): Promise { // Atomic NX check: do not yield between reading and writing. const entry = this.entries.get(key); if (options.nx && entry && entry.expiresAt > Date.now()) return false; this.entries.set(key, { value, expiresAt: Date.now() + (options.pxMs ?? 1000) }); return true; } async eval(script: string, keys: string[], args: string[]): Promise { const key = keys[0] ?? ""; const entry = this.entries.get(key); if (!entry || entry.value !== args[0] || entry.expiresAt <= Date.now()) return 0; if (script.includes("PEXPIRE")) entry.expiresAt = Date.now() + Number(args[1]); else this.entries.delete(key); return 1; } close(): void {} }