Files
Eric Allam 5ba8557a51 chore(webapp,core): remove the end-of-life v3 (engine V1) execution stack (#4236)
## Summary

v3 (the engine that ran the SDK v3 era, internally
`RunEngineVersion.V1`) is end-of-life. Following the removal of the v3
execution apps
([#4194](https://github.com/triggerdotdev/trigger.dev/pull/4194)) and
the legacy dev websocket
([#4198](https://github.com/triggerdotdev/trigger.dev/pull/4198)), this
removes the remaining v3 execution stack from the server.

Clients still on v3 (an old SDK or CLI that has not upgraded) keep
getting a clear "upgrade to v4" response. Triggers, batch triggers,
reschedules, and deploys that resolve to v3 are rejected with a graceful
4xx pointing at the migration guide, never a 5xx, so a stale client
cannot affect server health. Self-hosted instances still running v3
should stay on the 4.5.x release line until they migrate.

## What is removed

- The MarQS queue and its shared/dev queue consumers.
- The v3 socket.io namespaces (coordinator, provider, shared-queue) and
the v3 run lifecycle services (attempt, checkpoint, and batch-resume).
- The graphile-worker background job system; all live jobs already run
on `@trigger.dev/redis-worker`.
- The `DEPRECATE_V3_ENABLED` flag: v3 is now rejected unconditionally,
so the flag is gone.
- Unused v3 exports from `@trigger.dev/core` (the `v3/zodNamespace`
subpath and the legacy socket message catalogs) and the now-dead MarQS
environment variables.

## What stays

The v4 engine is untouched. The graceful v3 rejection boundary stays,
`determineEngineVersion` still detects a v3 project so it can reject it,
and the batch service plus batch-completion worker stay for current
clients. Live queue concurrency limits and metrics now read from the v4
run engine instead of MarQS, and a brand-new dev environment now
defaults to v4.



## Dependency cleanup

Removes webapp dependencies left unused by this change: `seedrandom` and
`semver` (only the removed v3 code used them) plus a set that was
already dead, their orphaned `@types` packages, and two dead files. Adds
a `knip:deps` script and a `knip.json` config so unused dependencies can
be found the same way going forward.
2026-07-13 11:32:06 +01:00

83 lines
2.4 KiB
TypeScript

import { RunEngineVersion, type RuntimeEnvironmentType } from "@trigger.dev/database";
import { $replica } from "~/db.server";
import {
findCurrentWorkerFromEnvironment,
getCurrentWorkerDeploymentEngineVersion,
} from "./models/workerDeployment.server";
// Co-locate the per-env run-ops residency/mint decision next to the
// engine-version decision. determineEngineVersion is intentionally left untouched so its
// read-only callers (presenters, admin routes, pauseQueue) never pay the mint flag read.
export { resolveRunIdMintKind, type RunIdMintKind } from "./runOpsMigration/runOpsMintKind.server";
type Environment = {
id: string;
type: RuntimeEnvironmentType;
project: {
id: string;
engine: RunEngineVersion;
};
};
export async function determineEngineVersion({
environment,
workerVersion,
engineVersion: version,
}: {
environment: Environment;
workerVersion?: string;
engineVersion?: RunEngineVersion;
}): Promise<RunEngineVersion> {
if (version) {
return version;
}
// If the project is V1, then none of the background workers are running V2
if (environment.project.engine === RunEngineVersion.V1) {
return "V1";
}
/**
* The project has V2 enabled so it *could* be V2.
*/
// A specific worker version is requested
if (workerVersion) {
const worker = await $replica.backgroundWorker.findUnique({
select: {
engine: true,
},
where: {
projectId_runtimeEnvironmentId_version: {
projectId: environment.project.id,
runtimeEnvironmentId: environment.id,
version: workerVersion,
},
},
});
if (!worker) {
throw new Error(`Worker not found: environment: ${environment.id} version: ${workerVersion}`);
}
return worker.engine;
}
// Dev: use the latest BackgroundWorker. Default to V2 when there is no current
// worker: v3 (engine V1) is retired, so a fresh/idle dev env must resolve to V2.
if (environment.type === "DEVELOPMENT") {
const backgroundWorker = await findCurrentWorkerFromEnvironment(environment);
return backgroundWorker?.engine ?? "V2";
}
// Deployed: use the latest deployed BackgroundWorker
const currentDeploymentEngineVersion = await getCurrentWorkerDeploymentEngineVersion(
environment.id
);
if (currentDeploymentEngineVersion) {
return currentDeploymentEngineVersion;
}
return environment.project.engine;
}