/** * How much work is this pod still doing that is NOT an open HTTP request? * * The devserver hot-swaps a pod in place: on every successful webpack rebuild the child * re-imports the bundle, builds a fresh app, points the handler at it and closes the * previous one. That close used to be fire-and-forget — and it tears down the OLD app's * providers, which for a queue consumer means the BullMQ worker and its Redis * connection. A job running at that moment loses its lock renewal, so the lock sits * until its full TTL lapses and the stalled-checker cannot reclaim it: a `hazard_analyst` * step with a 3600 s `lockDuration` stalled for an hour, having already spent ~50k output * tokens, and the DB looked byte-identical to a slow model call (foodguard, 2026-08-27). * * Counting open HTTP requests would not have caught it — the job holds no request. So * the taps register their in-process work here, and the devserver waits for it to drain * before closing the old app. * * Published on a global rather than exported for import: the devserver child must read * it without depending on this package (instrumentation is optional — a pod runs * untapped when it is absent), exactly like `global.createChildApp`. */ /** The shape the devserver child reads off the global. Keep in sync with `main.devserver.ts`. */ export interface ActiveWorkSnapshot { /** In-process units of work currently running (queue jobs, and whatever else registers). */ count: number; /** When the longest-running one started, for reporting. */ oldestStartedAt?: number; } export declare function beginActiveWorkGeneration(): number; export declare function activeWorkGeneration(): number; /** * Register one unit of in-process work. Returns the "done" callback — call it in a * `finally` so a throwing job cannot leak a permanent +1 and wedge every future swap. * * `gen` attributes the work to an app generation. Omitted means UNATTRIBUTED, and * unattributed work counts toward every generation — the conservative direction: a drain * that waits too long costs bounded memory (the devserver caps concurrent drains), while * one that finishes too early kills a running job, which is the incident this exists to * prevent. */ export declare function beginActiveWork(gen?: number): () => void; /** Work in flight. With `gen`, only that generation's work plus anything unattributed. */ export declare function activeWorkSnapshot(gen?: number): ActiveWorkSnapshot; /** Publish the reader on the global so the devserver can poll it without importing us. */ export declare function installActiveWorkProbe(): void; /** Tests only. */ export declare function resetActiveWorkForTests(): void;