import { ISagaStateStore } from '../application/sagas/ISagaStateStore'; interface StoredItem { value: string; expiry: number; } export class InMemorySagaStateStore implements ISagaStateStore { private store = new Map(); private locks = new Set(); async get(key: string): Promise { const item = this.store.get(key); if (!item || Date.now() > item.expiry) { this.store.delete(key); return null; } return item.value; } async setex(key: string, ttlSeconds: number, value: string): Promise { const expiry = Date.now() + ttlSeconds * 1000; this.store.set(key, { value, expiry }); // Clean up expired items after TTL setTimeout(() => { const item = this.store.get(key); if (item && Date.now() > item.expiry) { this.store.delete(key); } }, ttlSeconds * 1000); } async del(key: string): Promise { this.store.delete(key); this.locks.delete(key); } async set( key: string, value: string, mode: 'EX', ttl: number, flag: 'NX', ): Promise<'OK' | null> { if (flag === 'NX' && this.locks.has(key)) { return null; // Lock already exists } this.locks.add(key); // Auto-expire the lock after TTL setTimeout(() => { this.locks.delete(key); }, ttl * 1000); return 'OK'; } /** * Clear all data (useful for testing) */ clear(): void { this.store.clear(); this.locks.clear(); } }