d59743bd35
## Summary Three fixes to the run-ops database split (the Cloud-only mode where run-lifecycle rows live on a dedicated Postgres). All are inert in the default single-database deployment. The main fix: on the batch trigger paths, a parentless batch's item runs chose their physical store from a fresh per-org mint-flag read at processing time, so flipping an org's flag mid-batch could land an item in a different store than its batch, breaking the `TaskRun.batchId` foreign key (or silently orphaning the item). The other two harden the split's safety nets: the schema-parity test now actually compares columns, and the read fan-out gate now signals when it has been silently disabled. ## Batch item residency `RunEngineBatchTriggerService` (api.v2) and the BatchQueue item callback (api.v3) now anchor each item's id mint on the batch's own friendlyId, mirroring the already-safe `BatchTriggerV3Service`. Residency is a pure id-shape check, so an item can no longer diverge from its batch across a mid-batch flag flip. The pre-failed-run fallback is anchored the same way (it also sets `batchId`), and the shared mint branch is consolidated into one helper so every mint path stays in lockstep. No new database queries; single-database mode is unchanged (a cuid-shaped batch friendlyId yields a cuid item). ## Schema parity test The parity test previously read only the dedicated schema and matched model headers with regexes, so it never compared columns and could not catch a run-subgraph column that diverged between the two physical schemas. It now parses both schemas and asserts bidirectional scalar-column parity (type, nullability, array-ness, default) across the run-subgraph models, and fails on any field line it can't parse. Scoped to the run-subgraph models so unrelated control-plane edits don't break it. ## Read fan-out signal The split read fan-out gate is decided by the object identity of the NEW vs control-plane clients. It now warns when both run-ops URLs are set but the NEW client isn't a distinct instance (fan-out silently off), and a new test exercises the real topology-into-gate wiring so a future refactor that aliases the clients can't disable fan-out unnoticed. ## Verification New unit and glue tests cover all three changes; the DB-backed residency, store-routing, and topology suites pass against real Postgres; `typecheck` is clean for both packages.
43 lines
1.6 KiB
TypeScript
43 lines
1.6 KiB
TypeScript
import { describe, expect, it, vi } from "vitest";
|
|
|
|
// Empty singletons satisfy the module-level wiring imports; the mint method under test is driven
|
|
// directly via (service as any) and never touches the DB (same boundary as triggerTask.server.test.ts).
|
|
vi.mock("~/db.server", () => ({
|
|
prisma: {},
|
|
$replica: {},
|
|
runOpsNewPrisma: {},
|
|
runOpsLegacyPrisma: {},
|
|
runOpsNewReplica: {},
|
|
runOpsLegacyReplica: {},
|
|
}));
|
|
vi.mock("~/v3/runOpsMigration/splitMode.server", () => ({ isSplitEnabled: async () => false }));
|
|
|
|
import { classifyKind, generateRunOpsId, RunId } from "@trigger.dev/core/v3/isomorphic";
|
|
import { TriggerFailedTaskService } from "./triggerFailedTask.server";
|
|
|
|
function buildService() {
|
|
return new TriggerFailedTaskService({ prisma: {} as any, engine: {} as any });
|
|
}
|
|
|
|
describe("TriggerFailedTaskService.mintFailedRunFriendlyId", () => {
|
|
it("returns the caller-supplied runFriendlyId verbatim (override wins over any mint)", async () => {
|
|
const override = RunId.toFriendlyId(generateRunOpsId());
|
|
const minted = await (buildService() as any).mintFailedRunFriendlyId({
|
|
organizationId: "org_1",
|
|
environmentId: "env_1",
|
|
runFriendlyId: override,
|
|
});
|
|
expect(minted).toBe(override);
|
|
});
|
|
|
|
it("without an override, still inherits a run-ops (NEW) parent by id-shape", async () => {
|
|
const parentRunFriendlyId = RunId.toFriendlyId(generateRunOpsId());
|
|
const minted = await (buildService() as any).mintFailedRunFriendlyId({
|
|
organizationId: "org_1",
|
|
environmentId: "env_1",
|
|
parentRunFriendlyId,
|
|
});
|
|
expect(classifyKind(minted)).toBe("runOpsId");
|
|
});
|
|
});
|