chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:32:57 +08:00
commit cd420f9332
4811 changed files with 884702 additions and 0 deletions
+671
View File
@@ -0,0 +1,671 @@
import { containerTest, heteroPostgresTest } from "@internal/testcontainers";
import { PostgresRunStore } from "@internal/run-store";
import type { PrismaClient } from "@trigger.dev/database";
import type { CompleteBatchResult } from "@internal/run-engine";
import { describe, expect, vi } from "vitest";
import {
handleBatchCompletion,
readRunForEvent,
readRunForEventOrThrow,
resolveBatchRunOpsWriter,
type BatchCompletionDeps,
type EventReadDeps,
} from "~/v3/runEngineHandlersShared.server";
vi.setConfig({ testTimeout: 60_000 });
// Proves two routing properties against REAL Postgres (never mocked):
// 1. the 7 TaskRun event reads resolve run-ops new-or-old via read-through;
// 2. the batch update + error-createMany transaction commits entirely on the
// run-ops writer that owns the BatchTaskRun row (no boundary-spanning txn).
const EVENT_SELECT = {
id: true,
friendlyId: true,
traceId: true,
spanId: true,
parentSpanId: true,
createdAt: true,
completedAt: true,
taskIdentifier: true,
projectId: true,
runtimeEnvironmentId: true,
environmentType: true,
isTest: true,
organizationId: true,
taskEventStore: true,
runTags: true,
batchId: true,
} as const;
async function seedEnvironment(prisma: PrismaClient, slugSuffix: string) {
const organization = await prisma.organization.create({
data: { title: `Org ${slugSuffix}`, slug: `org-${slugSuffix}` },
});
const project = await prisma.project.create({
data: {
name: `Project ${slugSuffix}`,
slug: `project-${slugSuffix}`,
externalRef: `proj_${slugSuffix}`,
organizationId: organization.id,
},
});
const environment = await prisma.runtimeEnvironment.create({
data: {
type: "DEVELOPMENT",
slug: "dev",
projectId: project.id,
organizationId: organization.id,
apiKey: `tr_dev_${slugSuffix}`,
pkApiKey: `pk_dev_${slugSuffix}`,
shortcode: `short_${slugSuffix}`,
},
});
return { organization, project, environment };
}
async function seedTaskRun(
prisma: PrismaClient,
params: {
id: string;
friendlyId: string;
organizationId: string;
projectId: string;
runtimeEnvironmentId: string;
runTags?: string[];
}
) {
return prisma.taskRun.create({
data: {
id: params.id,
engine: "V2",
status: "COMPLETED_SUCCESSFULLY",
friendlyId: params.friendlyId,
taskIdentifier: "my-task",
payload: '{"hello":"world"}',
payloadType: "application/json",
traceId: "trace_1",
spanId: "span_1",
queue: "task/my-task",
runtimeEnvironmentId: params.runtimeEnvironmentId,
projectId: params.projectId,
organizationId: params.organizationId,
environmentType: "DEVELOPMENT",
isTest: false,
taskEventStore: "taskEvent",
runTags: params.runTags ?? ["alpha", "beta"],
createdAt: new Date("2024-01-01T00:00:00.000Z"),
completedAt: new Date("2024-01-01T00:01:00.000Z"),
},
});
}
async function seedBatch(
prisma: PrismaClient,
params: { id: string; friendlyId: string; runtimeEnvironmentId: string }
) {
return prisma.batchTaskRun.create({
data: {
id: params.id,
friendlyId: params.friendlyId,
runtimeEnvironmentId: params.runtimeEnvironmentId,
status: "PENDING",
},
});
}
function makeBatchDeps(
overrides: {
splitEnabled?: boolean;
newReplica?: PrismaClient;
newWriter?: PrismaClient;
legacyWriter?: PrismaClient;
legacyReplica?: PrismaClient;
} & { single?: PrismaClient }
): BatchCompletionDeps & { tryCompleteBatchCalls: string[] } {
const single = overrides.single;
const tryCompleteBatchCalls: string[] = [];
return {
splitEnabled: overrides.splitEnabled ?? false,
newReplica: (overrides.newReplica ?? single)!,
newWriter: (overrides.newWriter ?? single)!,
legacyWriter: (overrides.legacyWriter ?? single)!,
tryCompleteBatch: async (batchId: string) => {
tryCompleteBatchCalls.push(batchId);
},
tryCompleteBatchCalls,
};
}
function failure(index: number, errorCode: string, extra?: Record<string, unknown>) {
return {
index,
taskIdentifier: "my-task",
payload: '{"item":' + index + "}",
options: { foo: "bar" },
error: `error ${index}`,
errorCode,
timestamp: Date.now(),
...extra,
};
}
describe("runEngineHandlers read-through", () => {
// A NEW run resolves via read-through against the new store.
containerTest("event read resolves a NEW run via read-through", async ({ prisma }) => {
const store = new PostgresRunStore({ prisma, readOnlyPrisma: prisma });
const { organization, project, environment } = await seedEnvironment(prisma, "a");
await seedTaskRun(prisma, {
id: "run_new_a",
friendlyId: "run_friendly_a",
organizationId: organization.id,
projectId: project.id,
runtimeEnvironmentId: environment.id,
runTags: ["x", "y"],
});
const deps: EventReadDeps = {
store,
newReplica: prisma,
legacyReplica: prisma,
splitEnabled: false,
};
const run = await readRunForEvent("run_new_a", environment.id, EVENT_SELECT, deps);
expect(run).not.toBeNull();
expect(run!.id).toBe("run_new_a");
expect(run!.friendlyId).toBe("run_friendly_a");
expect(run!.runTags).toEqual(["x", "y"]);
expect(run!.organizationId).toBe(organization.id);
expect(run!.taskEventStore).toBe("taskEvent");
});
// Single-DB short-circuit — readLegacy must never be invoked.
containerTest("single-DB short-circuit never touches a legacy handle", async ({ prisma }) => {
const store = new PostgresRunStore({ prisma, readOnlyPrisma: prisma });
const { organization, project, environment } = await seedEnvironment(prisma, "c");
await seedTaskRun(prisma, {
id: "run_single_c",
friendlyId: "run_friendly_c",
organizationId: organization.id,
projectId: project.id,
runtimeEnvironmentId: environment.id,
});
// A legacy replica that THROWS if read — proves the short-circuit.
const exploding = new Proxy(
{},
{
get() {
throw new Error("legacy replica must not be touched in single-DB mode");
},
}
) as unknown as PrismaClient;
const deps: EventReadDeps = {
store,
newReplica: prisma,
legacyReplica: exploding,
splitEnabled: false,
};
const run = await readRunForEvent("run_single_c", environment.id, EVENT_SELECT, deps);
expect(run!.id).toBe("run_single_c");
});
// readRunForEventOrThrow reproduces the not-found-as-error semantics.
containerTest("readRunForEventOrThrow throws on a missing run", async ({ prisma }) => {
const store = new PostgresRunStore({ prisma, readOnlyPrisma: prisma });
await seedEnvironment(prisma, "nf");
const deps: EventReadDeps = {
store,
newReplica: prisma,
legacyReplica: prisma,
splitEnabled: false,
};
await expect(
readRunForEventOrThrow("run_missing", "env_x", EVENT_SELECT, deps)
).rejects.toThrow();
// Nullable helper returns null instead of throwing for the same input.
const run = await readRunForEvent("run_missing", "env_x", EVENT_SELECT, deps);
expect(run).toBeNull();
});
});
describe("runEngineHandlers read-through cross-version", () => {
// An OLD in-retention run is served off the LEGACY REPLICA only, and the legacy
// primary/writer is structurally absent.
heteroPostgresTest(
"event read resolves an OLD in-retention run via the legacy replica",
async ({ prisma14, prisma17 }) => {
const newStore = new PostgresRunStore({ prisma: prisma17, readOnlyPrisma: prisma17 });
const legacyStore = new PostgresRunStore({ prisma: prisma14, readOnlyPrisma: prisma14 });
const legacySeed = await seedEnvironment(prisma14, "b14");
// A 25-char cuid id classifies as LEGACY so read-through probes new, misses,
// then falls back to the legacy replica.
const legacyRunId = "c".repeat(25);
const seededRow = await seedTaskRun(prisma14, {
id: legacyRunId,
friendlyId: "run_friendly_b",
organizationId: legacySeed.organization.id,
projectId: legacySeed.project.id,
runtimeEnvironmentId: legacySeed.environment.id,
runTags: ["legacy", "tag"],
});
// The read uses the NEW store for the new-DB probe and the LEGACY store for
// the replica fallback, so a hit can only come from the legacy replica.
let legacyReplicaUsed = false;
// A store facade that routes the read to the legacy store when handed the
// legacy client and the new store otherwise — both real DBs, no mocks.
const routedStore = {
...newStore,
findRun: ((where: any, args: any, client: any) => {
if (client === prisma14) {
legacyReplicaUsed = true;
return legacyStore.findRun(where, args, client);
}
return newStore.findRun(where, args, client);
}) as typeof newStore.findRun,
} as PostgresRunStore;
const routedDeps: EventReadDeps = {
store: routedStore,
newReplica: prisma17,
legacyReplica: prisma14,
splitEnabled: true,
};
const run = await readRunForEvent(
legacyRunId,
legacySeed.environment.id,
EVENT_SELECT,
routedDeps
);
expect(legacyReplicaUsed).toBe(true);
expect(run).not.toBeNull();
expect(run!.id).toBe(legacyRunId);
// Byte-identity of the enrichment select across the legacy<->new boundary:
// re-read the same row on the legacy replica directly and deep-equal it.
const direct = await legacyStore.findRun(
{ id: legacyRunId },
{ select: EVENT_SELECT },
prisma14
);
expect(run).toEqual(direct);
expect(run!.runTags).toEqual(["legacy", "tag"]);
expect(seededRow.id).toBe(legacyRunId);
// The new DB has no such run.
const onNew = await newStore.findRun({ id: legacyRunId }, { select: EVENT_SELECT }, prisma17);
expect(onNew).toBeNull();
}
);
});
describe("runEngineHandlers batch completion", () => {
// Tests D + F: the txn commits whole on a single run-ops writer; rolls back atomically.
containerTest("batch txn commits whole on the run-ops writer", async ({ prisma }) => {
const { environment } = await seedEnvironment(prisma, "d");
const batchId = "c".repeat(25);
await seedBatch(prisma, {
id: batchId,
friendlyId: "batch_friendly_d",
runtimeEnvironmentId: environment.id,
});
const deps = makeBatchDeps({ single: prisma, splitEnabled: false });
const result: CompleteBatchResult = {
batchId,
runIds: ["run_friendly_1", "run_friendly_2"],
successfulRunCount: 2,
failedRunCount: 1,
failures: [failure(0, "TRIGGER_ERROR", { options: { nested: { a: 1, b: [2, 3] } } })],
};
await handleBatchCompletion(result, deps);
const batch = await prisma.batchTaskRun.findFirstOrThrow({ where: { id: batchId } });
expect(batch.status).toBe("PARTIAL_FAILED");
expect(batch.runIds).toEqual(["run_friendly_1", "run_friendly_2"]);
expect(batch.successfulRunCount).toBe(2);
expect(batch.failedRunCount).toBe(1);
expect(batch.processingCompletedAt).not.toBeNull();
const errors = await prisma.batchTaskRunError.findMany({ where: { batchTaskRunId: batchId } });
expect(errors).toHaveLength(1);
expect(errors[0]!.errorCode).toBe("TRIGGER_ERROR");
// JSON round-trip of options.
expect(errors[0]!.options).toEqual({ nested: { a: 1, b: [2, 3] } });
// PARTIAL_FAILED (not ABORTED) -> tryCompleteBatch is invoked.
expect(deps.tryCompleteBatchCalls).toEqual([batchId]);
});
// Atomicity: if the createMany fails, the update rolls back too.
containerTest("batch txn rolls back the update when createMany fails", async ({ prisma }) => {
const { environment } = await seedEnvironment(prisma, "rb");
const batchId = "d".repeat(25);
await seedBatch(prisma, {
id: batchId,
friendlyId: "batch_friendly_rb",
runtimeEnvironmentId: environment.id,
});
const deps = makeBatchDeps({ single: prisma, splitEnabled: false });
// A failure with a null taskIdentifier violates the NOT NULL constraint inside
// the createMany, forcing the whole transaction to roll back.
const result = {
batchId,
runIds: ["run_friendly_1"],
successfulRunCount: 0,
failedRunCount: 1,
failures: [
{ index: 0, taskIdentifier: null as any, payload: "{}", error: "boom", timestamp: 1 },
],
} as unknown as CompleteBatchResult;
await expect(handleBatchCompletion(result, deps)).rejects.toThrow();
// The update must NOT have committed — status stays PENDING from the seed.
const batch = await prisma.batchTaskRun.findFirstOrThrow({ where: { id: batchId } });
expect(batch.status).toBe("PENDING");
expect(batch.processingCompletedAt).toBeNull();
});
// Callback retry is idempotent via skipDuplicates.
containerTest("batch txn is idempotent on callback retry", async ({ prisma }) => {
const { environment } = await seedEnvironment(prisma, "e");
const batchId = "e".repeat(25);
await seedBatch(prisma, {
id: batchId,
friendlyId: "batch_friendly_e",
runtimeEnvironmentId: environment.id,
});
const deps = makeBatchDeps({ single: prisma, splitEnabled: false });
const result: CompleteBatchResult = {
batchId,
runIds: [],
successfulRunCount: 0,
failedRunCount: 2,
failures: [failure(0, "TRIGGER_ERROR"), failure(1, "TRIGGER_ERROR")],
};
await handleBatchCompletion(result, deps);
await handleBatchCompletion(result, deps);
const errors = await prisma.batchTaskRunError.findMany({ where: { batchTaskRunId: batchId } });
expect(errors).toHaveLength(2);
});
// Aggregate fast-path collapses same-errorCode failures to one row.
containerTest("aggregate fast-path collapses queue-size-limit failures", async ({ prisma }) => {
const { environment } = await seedEnvironment(prisma, "i");
const batchId = "f".repeat(25);
await seedBatch(prisma, {
id: batchId,
friendlyId: "batch_friendly_i",
runtimeEnvironmentId: environment.id,
});
const deps = makeBatchDeps({ single: prisma, splitEnabled: false });
const result: CompleteBatchResult = {
batchId,
runIds: [],
successfulRunCount: 0,
failedRunCount: 3,
failures: [
failure(5, "QUEUE_SIZE_LIMIT_EXCEEDED"),
failure(6, "QUEUE_SIZE_LIMIT_EXCEEDED"),
failure(7, "QUEUE_SIZE_LIMIT_EXCEEDED"),
],
};
await handleBatchCompletion(result, deps);
const errors = await prisma.batchTaskRunError.findMany({ where: { batchTaskRunId: batchId } });
expect(errors).toHaveLength(1);
expect(errors[0]!.index).toBe(5);
expect(errors[0]!.error).toContain("(3 items in this batch failed with the same error)");
});
// ABORTED status does not call tryCompleteBatch.
containerTest("ABORTED batch does not call tryCompleteBatch", async ({ prisma }) => {
const { environment } = await seedEnvironment(prisma, "ab");
const batchId = "g".repeat(25);
await seedBatch(prisma, {
id: batchId,
friendlyId: "batch_friendly_ab",
runtimeEnvironmentId: environment.id,
});
const deps = makeBatchDeps({ single: prisma, splitEnabled: false });
const result: CompleteBatchResult = {
batchId,
runIds: [],
successfulRunCount: 0,
failedRunCount: 1,
failures: [failure(0, "TRIGGER_ERROR")],
};
await handleBatchCompletion(result, deps);
const batch = await prisma.batchTaskRun.findFirstOrThrow({ where: { id: batchId } });
expect(batch.status).toBe("ABORTED");
expect(batch.completedAt).not.toBeNull();
expect(deps.tryCompleteBatchCalls).toEqual([]);
});
// A successful (no-failure) batch is PENDING and calls tryCompleteBatch.
containerTest("successful batch is PENDING and calls tryCompleteBatch", async ({ prisma }) => {
const { environment } = await seedEnvironment(prisma, "ok");
const batchId = "h".repeat(25);
await seedBatch(prisma, {
id: batchId,
friendlyId: "batch_friendly_ok",
runtimeEnvironmentId: environment.id,
});
const deps = makeBatchDeps({ single: prisma, splitEnabled: false });
const result: CompleteBatchResult = {
batchId,
runIds: ["run_friendly_1"],
successfulRunCount: 1,
failedRunCount: 0,
failures: [],
};
await handleBatchCompletion(result, deps);
const batch = await prisma.batchTaskRun.findFirstOrThrow({ where: { id: batchId } });
expect(batch.status).toBe("PENDING");
expect(deps.tryCompleteBatchCalls).toEqual([batchId]);
});
});
describe("runEngineHandlers batch residency routing", () => {
// True single-DB invariant: the topology's cpFallback makes newReplica and
// legacyWriter the SAME control-plane client, so the probe always resolves to
// that one client regardless of where length-classification would guess.
containerTest("true single-DB resolves to the single client", async ({ prisma }) => {
const { environment } = await seedEnvironment(prisma, "single");
const batchId = "s".repeat(25);
await seedBatch(prisma, {
id: batchId,
friendlyId: "batch_friendly_single",
runtimeEnvironmentId: environment.id,
});
const writer = await resolveBatchRunOpsWriter(batchId, {
newReplica: prisma,
newWriter: prisma,
legacyWriter: prisma,
});
expect(writer).toBe(prisma);
});
// A legacy-resident batch (row only on the legacy DB) commits on the LEGACY writer;
// the NEW DB is left with zero rows for the batch.
heteroPostgresTest(
"legacy-resident batch routes to the LEGACY writer, new DB untouched",
async ({ prisma14, prisma17 }) => {
const legacySeed = await seedEnvironment(prisma14, "g14");
const batchId = "c".repeat(25);
await seedBatch(prisma14, {
id: batchId,
friendlyId: "batch_friendly_g",
runtimeEnvironmentId: legacySeed.environment.id,
});
// The probe misses on new (the new DB has no such batch) and resolves the legacy writer.
const writer = await resolveBatchRunOpsWriter(batchId, {
newReplica: prisma17,
newWriter: prisma17,
legacyWriter: prisma14,
});
expect(writer).toBe(prisma14);
const deps: BatchCompletionDeps = {
splitEnabled: true,
newReplica: prisma17,
newWriter: prisma17,
legacyWriter: prisma14,
tryCompleteBatch: async () => {},
};
const result: CompleteBatchResult = {
batchId,
runIds: ["run_friendly_1"],
successfulRunCount: 1,
failedRunCount: 1,
failures: [failure(0, "TRIGGER_ERROR")],
};
await handleBatchCompletion(result, deps);
// Committed on the legacy DB.
const legacyBatch = await prisma14.batchTaskRun.findFirstOrThrow({ where: { id: batchId } });
expect(legacyBatch.status).toBe("PARTIAL_FAILED");
const legacyErrors = await prisma14.batchTaskRunError.findMany({
where: { batchTaskRunId: batchId },
});
expect(legacyErrors).toHaveLength(1);
// The new DB has zero rows for this batch — no misroute.
const onNew = await prisma17.batchTaskRun.findMany({ where: { id: batchId } });
expect(onNew).toHaveLength(0);
const newErrors = await prisma17.batchTaskRunError.findMany({
where: { batchTaskRunId: batchId },
});
expect(newErrors).toHaveLength(0);
}
);
// Regression: the real "run-ops DB connected, split flag off" state. splitEnabled
// is false, yet newWriter is a DISTINCT (empty) DB while the batch lives on legacy.
// Old code wrote to newWriter -> "No record was found for an update" -> batch hangs.
heteroPostgresTest(
"split-off connected-but-off: legacy-resident batch routes to LEGACY, not newWriter",
async ({ prisma14, prisma17 }) => {
const legacySeed = await seedEnvironment(prisma14, "off14");
const batchId = "c".repeat(25);
await seedBatch(prisma14, {
id: batchId,
friendlyId: "batch_friendly_off",
runtimeEnvironmentId: legacySeed.environment.id,
});
const deps: BatchCompletionDeps = {
splitEnabled: false,
newReplica: prisma17,
newWriter: prisma17,
legacyWriter: prisma14,
tryCompleteBatch: async () => {},
};
const result: CompleteBatchResult = {
batchId,
runIds: ["run_friendly_1"],
successfulRunCount: 1,
failedRunCount: 1,
failures: [failure(0, "TRIGGER_ERROR")],
};
await handleBatchCompletion(result, deps);
// Committed on the legacy DB; the new DB (the distinct newWriter) untouched.
const legacyBatch = await prisma14.batchTaskRun.findFirstOrThrow({ where: { id: batchId } });
expect(legacyBatch.status).toBe("PARTIAL_FAILED");
expect(legacyBatch.processingCompletedAt).not.toBeNull();
const legacyErrors = await prisma14.batchTaskRunError.findMany({
where: { batchTaskRunId: batchId },
});
expect(legacyErrors).toHaveLength(1);
const onNew = await prisma17.batchTaskRun.findMany({ where: { id: batchId } });
expect(onNew).toHaveLength(0);
const newErrors = await prisma17.batchTaskRunError.findMany({
where: { batchTaskRunId: batchId },
});
expect(newErrors).toHaveLength(0);
}
);
// A new batch (row only on the new DB) commits on the NEW writer; the LEGACY DB is untouched.
heteroPostgresTest(
"new batch routes to the NEW writer, legacy DB untouched",
async ({ prisma14, prisma17 }) => {
const newSeed = await seedEnvironment(prisma17, "h17");
const batchId = "d".repeat(25);
await seedBatch(prisma17, {
id: batchId,
friendlyId: "batch_friendly_h",
runtimeEnvironmentId: newSeed.environment.id,
});
const writer = await resolveBatchRunOpsWriter(batchId, {
newReplica: prisma17,
newWriter: prisma17,
legacyWriter: prisma14,
});
expect(writer).toBe(prisma17);
const deps: BatchCompletionDeps = {
splitEnabled: true,
newReplica: prisma17,
newWriter: prisma17,
legacyWriter: prisma14,
tryCompleteBatch: async () => {},
};
const result: CompleteBatchResult = {
batchId,
runIds: ["run_friendly_1"],
successfulRunCount: 1,
failedRunCount: 1,
failures: [failure(0, "TRIGGER_ERROR", { options: { json: { deep: [1, 2, 3] } } })],
};
await handleBatchCompletion(result, deps);
const newBatch = await prisma17.batchTaskRun.findFirstOrThrow({ where: { id: batchId } });
expect(newBatch.status).toBe("PARTIAL_FAILED");
const newErrors = await prisma17.batchTaskRunError.findMany({
where: { batchTaskRunId: batchId },
});
expect(newErrors).toHaveLength(1);
// Batch JSON round-trip on the new DB.
expect(newErrors[0]!.options).toEqual({ json: { deep: [1, 2, 3] } });
// The legacy DB is untouched.
const onLegacy = await prisma14.batchTaskRun.findMany({ where: { id: batchId } });
expect(onLegacy).toHaveLength(0);
}
);
});