@tanstack/db
Version:
A reactive client store for building super fast apps on sync
1 lines • 4.3 kB
Source Map (JSON)
{"version":3,"file":"cleanup-queue.cjs","sources":["../../../src/collection/cleanup-queue.ts"],"sourcesContent":["type CleanupTask = {\n executeAt: number\n callback: () => void\n}\n\n/**\n * Batches many GC registrations behind a single shared timeout.\n */\nexport class CleanupQueue {\n private static instance: CleanupQueue | null = null\n\n private tasks: Map<unknown, CleanupTask> = new Map()\n\n private timeoutId: ReturnType<typeof setTimeout> | null = null\n private microtaskScheduled = false\n\n private constructor() {}\n\n public static getInstance(): CleanupQueue {\n if (!CleanupQueue.instance) {\n CleanupQueue.instance = new CleanupQueue()\n }\n return CleanupQueue.instance\n }\n\n /**\n * Queues a cleanup task and defers timeout selection to a microtask so\n * multiple synchronous registrations can share one root timer.\n */\n public schedule(key: unknown, gcTime: number, callback: () => void): void {\n const executeAt = Date.now() + gcTime\n this.tasks.set(key, { executeAt, callback })\n\n if (!this.microtaskScheduled) {\n this.microtaskScheduled = true\n Promise.resolve().then(() => {\n this.microtaskScheduled = false\n this.updateTimeout()\n })\n }\n }\n\n public cancel(key: unknown): void {\n this.tasks.delete(key)\n }\n\n /**\n * Keeps only one active timeout: whichever task is due next.\n */\n private updateTimeout(): void {\n if (this.timeoutId !== null) {\n clearTimeout(this.timeoutId)\n this.timeoutId = null\n }\n\n if (this.tasks.size === 0) {\n return\n }\n\n let earliestTime = Infinity\n for (const task of this.tasks.values()) {\n if (task.executeAt < earliestTime) {\n earliestTime = task.executeAt\n }\n }\n\n const delay = Math.max(0, earliestTime - Date.now())\n this.timeoutId = setTimeout(() => this.process(), delay)\n }\n\n /**\n * Runs every task whose deadline has passed, then schedules the next wakeup\n * if there is still pending work.\n */\n private process(): void {\n this.timeoutId = null\n const now = Date.now()\n for (const [key, task] of this.tasks.entries()) {\n if (now >= task.executeAt) {\n this.tasks.delete(key)\n try {\n task.callback()\n } catch (error) {\n console.error('Error in CleanupQueue task:', error)\n }\n }\n }\n\n if (this.tasks.size > 0) {\n this.updateTimeout()\n }\n }\n\n /**\n * Resets the singleton instance for tests.\n */\n public static resetInstance(): void {\n if (CleanupQueue.instance) {\n if (CleanupQueue.instance.timeoutId !== null) {\n clearTimeout(CleanupQueue.instance.timeoutId)\n }\n CleanupQueue.instance = null\n }\n }\n}\n"],"names":[],"mappings":";;AAQO,MAAM,gBAAN,MAAM,cAAa;AAAA,EAQhB,cAAc;AALtB,SAAQ,4BAAuC,IAAA;AAE/C,SAAQ,YAAkD;AAC1D,SAAQ,qBAAqB;AAAA,EAEN;AAAA,EAEvB,OAAc,cAA4B;AACxC,QAAI,CAAC,cAAa,UAAU;AAC1B,oBAAa,WAAW,IAAI,cAAA;AAAA,IAC9B;AACA,WAAO,cAAa;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,SAAS,KAAc,QAAgB,UAA4B;AACxE,UAAM,YAAY,KAAK,IAAA,IAAQ;AAC/B,SAAK,MAAM,IAAI,KAAK,EAAE,WAAW,UAAU;AAE3C,QAAI,CAAC,KAAK,oBAAoB;AAC5B,WAAK,qBAAqB;AAC1B,cAAQ,UAAU,KAAK,MAAM;AAC3B,aAAK,qBAAqB;AAC1B,aAAK,cAAA;AAAA,MACP,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEO,OAAO,KAAoB;AAChC,SAAK,MAAM,OAAO,GAAG;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAsB;AAC5B,QAAI,KAAK,cAAc,MAAM;AAC3B,mBAAa,KAAK,SAAS;AAC3B,WAAK,YAAY;AAAA,IACnB;AAEA,QAAI,KAAK,MAAM,SAAS,GAAG;AACzB;AAAA,IACF;AAEA,QAAI,eAAe;AACnB,eAAW,QAAQ,KAAK,MAAM,OAAA,GAAU;AACtC,UAAI,KAAK,YAAY,cAAc;AACjC,uBAAe,KAAK;AAAA,MACtB;AAAA,IACF;AAEA,UAAM,QAAQ,KAAK,IAAI,GAAG,eAAe,KAAK,KAAK;AACnD,SAAK,YAAY,WAAW,MAAM,KAAK,QAAA,GAAW,KAAK;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,UAAgB;AACtB,SAAK,YAAY;AACjB,UAAM,MAAM,KAAK,IAAA;AACjB,eAAW,CAAC,KAAK,IAAI,KAAK,KAAK,MAAM,WAAW;AAC9C,UAAI,OAAO,KAAK,WAAW;AACzB,aAAK,MAAM,OAAO,GAAG;AACrB,YAAI;AACF,eAAK,SAAA;AAAA,QACP,SAAS,OAAO;AACd,kBAAQ,MAAM,+BAA+B,KAAK;AAAA,QACpD;AAAA,MACF;AAAA,IACF;AAEA,QAAI,KAAK,MAAM,OAAO,GAAG;AACvB,WAAK,cAAA;AAAA,IACP;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,gBAAsB;AAClC,QAAI,cAAa,UAAU;AACzB,UAAI,cAAa,SAAS,cAAc,MAAM;AAC5C,qBAAa,cAAa,SAAS,SAAS;AAAA,MAC9C;AACA,oBAAa,WAAW;AAAA,IAC1B;AAAA,EACF;AACF;AA/FE,cAAe,WAAgC;AAD1C,IAAM,eAAN;;"}