A social knowledge tool for researchers built on ATProto
at main 67 lines 1.5 kB view raw
1import { ISagaStateStore } from '../application/sagas/ISagaStateStore'; 2 3interface StoredItem { 4 value: string; 5 expiry: number; 6} 7 8export class InMemorySagaStateStore implements ISagaStateStore { 9 private store = new Map<string, StoredItem>(); 10 private locks = new Set<string>(); 11 12 async get(key: string): Promise<string | null> { 13 const item = this.store.get(key); 14 if (!item || Date.now() > item.expiry) { 15 this.store.delete(key); 16 return null; 17 } 18 return item.value; 19 } 20 21 async setex(key: string, ttlSeconds: number, value: string): Promise<void> { 22 const expiry = Date.now() + ttlSeconds * 1000; 23 this.store.set(key, { value, expiry }); 24 25 // Clean up expired items after TTL 26 setTimeout(() => { 27 const item = this.store.get(key); 28 if (item && Date.now() > item.expiry) { 29 this.store.delete(key); 30 } 31 }, ttlSeconds * 1000); 32 } 33 34 async del(key: string): Promise<void> { 35 this.store.delete(key); 36 this.locks.delete(key); 37 } 38 39 async set( 40 key: string, 41 value: string, 42 mode: 'EX', 43 ttl: number, 44 flag: 'NX', 45 ): Promise<'OK' | null> { 46 if (flag === 'NX' && this.locks.has(key)) { 47 return null; // Lock already exists 48 } 49 50 this.locks.add(key); 51 52 // Auto-expire the lock after TTL 53 setTimeout(() => { 54 this.locks.delete(key); 55 }, ttl * 1000); 56 57 return 'OK'; 58 } 59 60 /** 61 * Clear all data (useful for testing) 62 */ 63 clear(): void { 64 this.store.clear(); 65 this.locks.clear(); 66 } 67}