interface CacheEntry { data: any; cachedAt: Date; } class OrgStructureCache { private cache: Map = new Map(); private readonly CACHE_TTL = 30 * 60 * 1000; // 30 minutes private isInitialized = false; private cleanupTimer: NodeJS.Timeout | null = null; constructor() { // Don't auto-initialize - wait for AppDataSource to be ready } initialize() { if (this.isInitialized) return; this.isInitialized = true; // Cleanup expired entries every 30 minutes this.cleanupTimer = setInterval(() => { this.cleanup(); }, this.CACHE_TTL); console.log("[OrgStructureCache] Initialized"); } private generateKey(revisionId: string, rootId?: string): string { return `org-structure-${revisionId}-${rootId || "all"}`; } private cleanup() { const now = Date.now(); let cleaned = 0; for (const [key, entry] of this.cache.entries()) { const age = now - entry.cachedAt.getTime(); if (age > this.CACHE_TTL) { this.cache.delete(key); cleaned++; } } if (cleaned > 0) { console.log(`[OrgStructureCache] Cleaned ${cleaned} expired entries`); } } async get(revisionId: string, rootId?: string): Promise { const key = this.generateKey(revisionId, rootId); const entry = this.cache.get(key); if (!entry) { return null; } // Check if expired const age = Date.now() - entry.cachedAt.getTime(); if (age > this.CACHE_TTL) { this.cache.delete(key); return null; } console.log(`[OrgStructureCache] HIT: ${key}`); return entry.data; } async set(revisionId: string, rootId: string | undefined, data: any): Promise { const key = this.generateKey(revisionId, rootId); this.cache.set(key, { data, cachedAt: new Date(), }); console.log(`[OrgStructureCache] SET: ${key}`); } invalidate(revisionId: string): void { // Invalidate all entries for this revision for (const key of this.cache.keys()) { if (key.startsWith(`org-structure-${revisionId}`)) { this.cache.delete(key); } } console.log(`[OrgStructureCache] INVALIDATED: ${revisionId}`); } destroy() { if (this.cleanupTimer) { clearInterval(this.cleanupTimer); this.cleanupTimer = null; } this.cache.clear(); } } export const orgStructureCache = new OrgStructureCache();