freeze.worker.ts1.1 KBView on GitHub
// Heartbeat worker for freeze detection.
// Periodically pings the main thread. If main misses pings (because it's
// blocked on a long sync task), we know from the worker's clock how long
// it was blocked, and report back when main becomes responsive.

const PING_INTERVAL_MS = 250;
const FREEZE_THRESHOLD_MS = 750;

let lastPongAt = 0;
let frozenSince = 0;

self.onmessage = (e: MessageEvent) => {
  if (e.data?.type === 'pong') {
    const now = Date.now();
    if (frozenSince && now - lastPongAt > FREEZE_THRESHOLD_MS) {
      const blockedMs = now - lastPongAt;
      (self as unknown as Worker).postMessage({
        type: 'freeze',
        blockedMs,
        recoveredAt: now,
      });
    }
    lastPongAt = now;
    frozenSince = 0;
  } else if (e.data?.type === 'start') {
    lastPongAt = Date.now();
    setInterval(() => {
      const now = Date.now();
      if (lastPongAt && now - lastPongAt > FREEZE_THRESHOLD_MS) {
        // Main thread hasn't responded — mark frozen
        if (!frozenSince) frozenSince = now;
      }
      (self as unknown as Worker).postMessage({ type: 'ping' });
    }, PING_INTERVAL_MS);
  }
};