// WHICH LANE AN OPERATION RUNS ON. One function, one module. // // Its own file because it started as the arbiter's, and two things needed it // while neither could import the other: the arbiter planned units against it and // controller/operationJobs.ts reserves a queue key with it, while the arbiter // called operationJobs to start the jobs it planned. The arbiter retired in // slice 1.3; the module stays where it is, because a queue-key resolver is not // dispatch's private business. import { getSettings } from "../lib/settings"; import { EXTERNAL_OPERATIONS, getOperation, type Lane, } from "../lib/operations"; // The lane an operation runs on, or null when the registry does not know it. // // ONE RESOLUTION, off the kind's own declaration. A kind whose lane depends on // configuration says so with laneFor() — digest picks between the GPU-bound // local queue and the metered network one, diarization between contending for // the GPU and contending for cores — and a kind without one has a fixed lane. // This used to special-case digest here, which meant the rule lived in two // places and only digest's copy was live: diarization's laneFor was invisible // to every caller. // // THE REGISTRY FIRST, THEN THE EXTERNAL DECLARATIONS — slice 1.5. // // This used to answer null for download and transcription, on the argument that // a lane for them would let a caller "reserve the backfill queue for work no // backfill operation can do". That was never what a catalog lookup would have // done: their DECLARED lanes are `download:` and the transcription // queue, neither of which is BACKFILL_QUEUE. What the null actually cost was the // question every four-lane surface now asks — "which lane does this operation // run on" — coming back unanswered for the two lanes carrying 100% of live // dispatch. // // EXTERNAL_OPERATIONS only, not operationCatalog(): sync is catalogued beside // them and is a per-CHANNEL cadence, not a per-video pipeline, so it keeps the // null it has always had here and pauseGates.pauseLaneFor keeps saying so too. // // The one caller that reserves a queue key from this answer is // controller/operationJobs.runOperationChannelJob, and it is unaffected: it is // only ever handed a registry operation id (the /channels group buttons, the // channel page, the video page), and an external id would already have found no // kind to run. export function laneForOperation(operation: string): Lane | null { const kind = getOperation(operation); if (kind) return kind.laneFor?.(getSettings()) ?? kind.lane; return EXTERNAL_OPERATIONS.find((op) => op.id === operation)?.lane ?? null; }