diff --git a/apps/webapp/app/entry.server.tsx b/apps/webapp/app/entry.server.tsx index db72b0364c..60c234402d 100644 --- a/apps/webapp/app/entry.server.tsx +++ b/apps/webapp/app/entry.server.tsx @@ -30,8 +30,17 @@ import { // on webapp startup. The singleton's initializer wires start (gated on // `clickhouseFactory.isReady()`) and SIGTERM/SIGINT shutdown — mirrors // runsReplicationInstance. +// +// IMPORTANT: do NOT replace this with `void sessionsReplicationInstance;`. +// `apps/webapp/package.json` declares `"sideEffects": false`, so esbuild +// treats `void ;` as a pure expression statement and tree-shakes +// the entire import — the singleton's initializer never fires and the +// sessions→ClickHouse logical replication slot stops being consumed. Assigning +// to globalThis is an unambiguous side effect the bundler must preserve. See +// TRI-9864 for the incident write-up. import { sessionsReplicationInstance } from "./services/sessionsReplicationInstance.server"; -void sessionsReplicationInstance; +(globalThis as Record).__sessionsReplicationInstance = + sessionsReplicationInstance; const ABORT_DELAY = 30000; diff --git a/apps/webapp/app/v3/services/adminWorker.server.ts b/apps/webapp/app/v3/services/adminWorker.server.ts index 2e4d1b066c..cf3dbd57c6 100644 --- a/apps/webapp/app/v3/services/adminWorker.server.ts +++ b/apps/webapp/app/v3/services/adminWorker.server.ts @@ -6,10 +6,16 @@ import { logger } from "~/services/logger.server"; import { runsReplicationInstance } from "~/services/runsReplicationInstance.server"; // Reference-hold the sessions-replication singleton so module evaluation runs // its initializer (creates the ClickHouse client, subscribes to the logical -// replication slot, wires signal handlers) when the webapp boots. A bare -// side-effect import gets tree-shaken by the bundler. +// replication slot, wires signal handlers) when the webapp boots. +// +// IMPORTANT: do NOT replace with `void sessionsReplicationInstance;`. With +// `"sideEffects": false` in apps/webapp/package.json, esbuild treats `void X;` +// as a pure expression statement and eliminates the import — the singleton +// initializer never fires. Assignment to globalThis is an observable side +// effect the bundler must preserve. See TRI-9864. import { sessionsReplicationInstance } from "~/services/sessionsReplicationInstance.server"; -void sessionsReplicationInstance; +(globalThis as Record).__sessionsReplicationInstance = + sessionsReplicationInstance; import { singleton } from "~/utils/singleton"; import { tracer } from "../tracer.server"; import { $replica } from "~/db.server";