1tube 0.1.44 → 0.1.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "1tube",
3
- "version": "0.1.44",
3
+ "version": "0.1.45",
4
4
  "private": false,
5
5
  "description": "Self-hosted Supabase Edge Functions gateway for Deno, plus an ESLint plugin for consumers",
6
6
  "license": "MIT",
@@ -95,7 +95,10 @@ export interface DenoReloadDebouncerOptions {
95
95
  * `debounceMs`. Unset = classic trailing-only behavior.
96
96
  */
97
97
  leadingMs?: number;
98
- flushFn: (paths: readonly string[]) => Promise<void>;
98
+ // Awaited at the call site, so a synchronous callback is fine too (a test
99
+ // that just records the paths needn't be `async`, which would trip
100
+ // require-await). The real reloader flush is async.
101
+ flushFn: (paths: readonly string[]) => void | Promise<void>;
99
102
  setTimer?: (cb: () => void, ms: number) => number;
100
103
  clearTimer?: (id: number) => void;
101
104
  }
@@ -1188,6 +1188,13 @@ export function createDenoWorkerHost(
1188
1188
  */
1189
1189
  let coloReloadChain: Promise<unknown> = Promise.resolve();
1190
1190
 
1191
+ // In-flight worker-retirement drains. A retiring worker leaves `coloWorkers`
1192
+ // immediately but lingers (its `kill` armed on a timer) so in-flight
1193
+ // requests can finish. Tracked so `stop()` can both cancel the timer AND
1194
+ // run the kill now — otherwise the timer (and the Worker) outlive the host
1195
+ // and leak, which Deno's test sanitizer flags.
1196
+ const coloDrains = new Set<{ timer: number; kill: () => void }>();
1197
+
1191
1198
  interface ColoFnResult {
1192
1199
  name: string;
1193
1200
  ok: boolean;
@@ -1379,7 +1386,12 @@ export function createDenoWorkerHost(
1379
1386
  */
1380
1387
  function terminateColoWorker(w: Worker, drainMs: number): void {
1381
1388
  coloWorkers.delete(w);
1389
+ let entry: { timer: number; kill: () => void } | null = null;
1382
1390
  const kill = () => {
1391
+ if (entry) {
1392
+ clearTimeout(entry.timer);
1393
+ coloDrains.delete(entry);
1394
+ }
1383
1395
  try {
1384
1396
  w.terminate();
1385
1397
  } catch { /* already gone */ }
@@ -1390,8 +1402,13 @@ export function createDenoWorkerHost(
1390
1402
  }
1391
1403
  }
1392
1404
  };
1393
- if (drainMs > 0) setTimeout(kill, drainMs);
1394
- else kill();
1405
+ if (drainMs > 0) {
1406
+ const timer = setTimeout(kill, drainMs) as unknown as number;
1407
+ entry = { timer, kill };
1408
+ coloDrains.add(entry);
1409
+ } else {
1410
+ kill();
1411
+ }
1395
1412
  }
1396
1413
 
1397
1414
  /**
@@ -1768,6 +1785,11 @@ export function createDenoWorkerHost(
1768
1785
  }
1769
1786
 
1770
1787
  function stopColocated(): void {
1788
+ // Cancel + finish any in-flight retirement drains first: this clears their
1789
+ // timers and terminates the lingering workers (which already left
1790
+ // `coloWorkers`), so nothing outlives the host.
1791
+ for (const d of [...coloDrains]) d.kill();
1792
+ coloDrains.clear();
1771
1793
  for (const p of coloPending.values()) {
1772
1794
  p.reject(new Error("gateway shutting down"));
1773
1795
  }