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
@@ -0,0 +1,484 @@
import { Prisma } from "@trigger.dev/database";
import { describe, expect, vi } from "vitest";
// BatchListPresenter imports `~/db.server` (for `sqlDatabaseSchema` + `PrismaClientOrTransaction`),
// `~/models/runtimeEnvironment.server`, and `~/components/*` at load — all of which pull
// `env.server` at import time. Stub `~/db.server` to break that chain (the runsRepository
// read-through test does the same). The presenter is driven entirely through injected real
// containers; the only thing it actually reads off this module is `sqlDatabaseSchema`, which we
// reproduce as the real `Prisma.sql(["public"])` value so the schema-qualified raw scan SQL is valid.
vi.mock("~/db.server", () => ({
prisma: {},
$replica: {},
sqlDatabaseSchema: Prisma.sql(["public"]),
}));
import {
heteroPostgresTest,
heteroRunOpsPostgresTest,
postgresTest,
} from "@internal/testcontainers";
import type { PrismaClient } from "@trigger.dev/database";
import type { RunOpsPrismaClient } from "@internal/run-ops-database";
import {
type BatchListOptions,
BatchListPresenter,
} from "~/presenters/v3/BatchListPresenter.server";
vi.setConfig({ testTimeout: 120_000 });
type SeedContext = {
organizationId: string;
projectId: string;
environmentId: string;
userId: string;
};
// The exact presenter scan SQL, lifted verbatim, so tests can compare the presenter's output
// against a direct $queryRaw of the identical SQL on each DB version.
function rawScan(
prisma: PrismaClient,
opts: {
environmentId: string;
pageSize: number;
direction: "forward" | "backward";
cursor?: string;
}
) {
const { environmentId, pageSize, direction, cursor } = opts;
const sqlDatabaseSchema = Prisma.sql(["public"]);
return prisma.$queryRaw<
{
id: string;
friendlyId: string;
runtimeEnvironmentId: string;
status: any;
createdAt: Date;
updatedAt: Date;
completedAt: Date | null;
runCount: bigint;
batchVersion: string;
}[]
>`
SELECT
b.id,
b."friendlyId",
b."runtimeEnvironmentId",
b.status,
b."createdAt",
b."updatedAt",
b."completedAt",
b."runCount",
b."batchVersion"
FROM
${sqlDatabaseSchema}."BatchTaskRun" b
WHERE
b."runtimeEnvironmentId" = ${environmentId}
${
cursor
? direction === "forward"
? Prisma.sql`AND b.id < ${cursor}`
: Prisma.sql`AND b.id > ${cursor}`
: Prisma.empty
}
ORDER BY
${direction === "forward" ? Prisma.sql`b.id DESC` : Prisma.sql`b.id ASC`}
LIMIT ${pageSize + 1}`;
}
async function seedParents(prisma: PrismaClient, slug: string): Promise<SeedContext> {
const user = await prisma.user.create({
data: {
email: `user-${slug}@example.com`,
name: `User ${slug}`,
authenticationMethod: "MAGIC_LINK",
},
});
const organization = await prisma.organization.create({
data: { title: `org-${slug}`, slug: `org-${slug}` },
});
const project = await prisma.project.create({
data: {
name: `proj-${slug}`,
slug: `proj-${slug}`,
organizationId: organization.id,
externalRef: `proj-${slug}`,
},
});
const orgMember = await prisma.orgMember.create({
data: { organizationId: organization.id, userId: user.id },
});
const runtimeEnvironment = await prisma.runtimeEnvironment.create({
data: {
slug: `env-${slug}`,
type: "DEVELOPMENT",
projectId: project.id,
organizationId: organization.id,
orgMemberId: orgMember.id,
apiKey: `tr_dev_${slug}`,
pkApiKey: `pk_dev_${slug}`,
shortcode: `sc-${slug}`,
},
});
return {
organizationId: organization.id,
projectId: project.id,
environmentId: runtimeEnvironment.id,
userId: user.id,
};
}
// Mirrors the org/project/env parents onto a second DB with the SAME ids (BatchTaskRun FK needs
// the runtimeEnvironment to exist on whichever DB the row lives on).
async function mirrorEnvParents(
prisma: PrismaClient,
ctx: SeedContext,
slug: string
): Promise<void> {
const organization = await prisma.organization.create({
data: { id: ctx.organizationId, title: `org-${slug}`, slug: `org-${slug}` },
});
const project = await prisma.project.create({
data: {
id: ctx.projectId,
name: `proj-${slug}`,
slug: `proj-${slug}`,
organizationId: organization.id,
externalRef: `proj-${slug}`,
},
});
await prisma.runtimeEnvironment.create({
data: {
id: ctx.environmentId,
slug: `env-${slug}`,
type: "DEVELOPMENT",
projectId: project.id,
organizationId: organization.id,
apiKey: `tr_dev_${slug}_m`,
pkApiKey: `pk_dev_${slug}_m`,
shortcode: `sc-${slug}-m`,
},
});
}
async function createBatch(
prisma: PrismaClient,
ctx: SeedContext,
batch: {
id: string;
friendlyId: string;
status?: any;
batchVersion?: string;
runCount?: number;
createdAt?: Date;
}
) {
return prisma.batchTaskRun.create({
data: {
id: batch.id,
friendlyId: batch.friendlyId,
runtimeEnvironmentId: ctx.environmentId,
status: batch.status ?? "PENDING",
batchVersion: batch.batchVersion ?? "v3",
runCount: batch.runCount ?? 1,
...(batch.createdAt ? { createdAt: batch.createdAt } : {}),
},
});
}
const baseCall = (
ctx: SeedContext,
overrides: Partial<BatchListOptions> = {}
): BatchListOptions => ({
projectId: ctx.projectId,
environmentId: ctx.environmentId,
userId: ctx.userId,
...overrides,
});
// Wraps a prisma client so the test can assert whether/how often batchTaskRun.findMany or
// batchTaskRun.findFirst are invoked. Optionally throws if invoked (proves a handle is never touched).
function spyClient(
prisma: PrismaClient,
opts: { throwOnQueryRaw?: boolean; throwOnFindFirst?: boolean } = {}
) {
const counts = { queryRaw: 0, findMany: 0, findFirst: 0 };
const proxy = new Proxy(prisma, {
get(target, prop, receiver) {
if (prop === "batchTaskRun") {
const real = (target as any).batchTaskRun;
return new Proxy(real, {
get(trTarget, trProp) {
if (trProp === "findMany") {
return (...args: any[]) => {
counts.findMany++;
if (opts.throwOnQueryRaw)
throw new Error("batchTaskRun.findMany must not be invoked on this handle");
return (trTarget as any).findMany(...args);
};
}
if (trProp === "findFirst") {
return (...args: any[]) => {
counts.findFirst++;
if (opts.throwOnFindFirst)
throw new Error("batchTaskRun.findFirst must not be invoked on this handle");
return (trTarget as any).findFirst(...args);
};
}
return (trTarget as any)[trProp];
},
});
}
return Reflect.get(target, prop, receiver);
},
}) as unknown as PrismaClient;
return { client: proxy, counts };
}
const desc = (a: string, b: string) => (a < b ? 1 : a > b ? -1 : 0);
describe("BatchListPresenter run-ops read routing (PG14 control-plane/legacy + PG17 new)", () => {
// Byte-identical scan + identical ORDER-BY across PG14/PG17.
heteroPostgresTest(
"raw paginated scan is byte-identical and identically ordered across PG14 and PG17 (both directions, with/without cursor)",
async ({ prisma14, prisma17 }) => {
const ctx14 = await seedParents(prisma14, "scan");
const ctx17 = await seedParents(prisma17, "scan");
// Identical corpus on both sides (same logical ids), exercising statuses + batchVersion +
// createdAt spanning a period, and keyset cursor boundaries.
const ids = ["aaaa", "bbbb", "cccc", "dddd", "eeee"];
const statuses = ["PENDING", "COMPLETED", "ABORTED", "PROCESSING", "COMPLETED"];
const versions = ["v3", "v3", "v1", "v2", "v3"];
for (let i = 0; i < ids.length; i++) {
await createBatch(prisma14, ctx14, {
id: `batch_${ids[i]}`,
friendlyId: `fr_${ids[i]}`,
status: statuses[i],
batchVersion: versions[i],
runCount: i + 1,
createdAt: new Date(Date.now() - i * 60_000),
});
await createBatch(prisma17, ctx17, {
id: `batch_${ids[i]}`,
friendlyId: `fr_${ids[i]}`,
status: statuses[i],
batchVersion: versions[i],
runCount: i + 1,
createdAt: new Date(Date.now() - i * 60_000),
});
}
for (const direction of ["forward", "backward"] as const) {
for (const cursor of [undefined, "batch_cccc"]) {
const rows14 = await rawScan(prisma14, {
environmentId: ctx14.environmentId,
pageSize: 2,
direction,
cursor,
});
const rows17 = await rawScan(prisma17, {
environmentId: ctx17.environmentId,
pageSize: 2,
direction,
cursor,
});
// ids are identical across both DBs; rows must match byte-for-byte and in order.
expect(rows14.map((r) => r.id)).toEqual(rows17.map((r) => r.id));
expect(rows14.map((r) => r.friendlyId)).toEqual(rows17.map((r) => r.friendlyId));
expect(rows14.map((r) => r.runCount)).toEqual(rows17.map((r) => r.runCount));
expect(rows14.map((r) => r.status)).toEqual(rows17.map((r) => r.status));
// ORDER-BY parity: forward => id DESC, backward => id ASC.
const order = rows14.map((r) => r.id);
const expected = [...order].sort(direction === "forward" ? desc : (a, b) => -desc(a, b));
expect(order).toEqual(expected);
}
}
// The TS codepoint comparator reproduces the DB ORDER BY over the seeded id set.
const allIds = ids.map((i) => `batch_${i}`);
const dbForward = (
await rawScan(prisma17, {
environmentId: ctx17.environmentId,
pageSize: 50,
direction: "forward",
})
).map((r) => r.id);
expect(dbForward).toEqual([...allIds].sort(desc));
}
);
// Split scan merge serves new + legacy in one keyset-ordered page.
heteroPostgresTest(
"split scan merges new (PG17) + legacy (PG14) rows under the keyset order; legacy read only when new does not fill the page",
async ({ prisma14, prisma17 }) => {
const ctx14 = await seedParents(prisma14, "merge");
await mirrorEnvParents(prisma17, ctx14, "merge");
// Interleaved ids across the keyset order. New (migrated) on PG17, legacy on PG14.
await createBatch(prisma17, ctx14, { id: "batch_a", friendlyId: "fr_a", runCount: 1 });
await createBatch(prisma14, ctx14, { id: "batch_b", friendlyId: "fr_b", runCount: 2 });
await createBatch(prisma17, ctx14, { id: "batch_c", friendlyId: "fr_c", runCount: 3 });
await createBatch(prisma14, ctx14, { id: "batch_d", friendlyId: "fr_d", runCount: 4 });
await createBatch(prisma17, ctx14, { id: "batch_e", friendlyId: "fr_e", runCount: 5 });
// Case A: small page fully served by new alone => legacy NOT read.
const legacySpyA = spyClient(prisma14);
const presenterA = new BatchListPresenter(prisma17, prisma17, {
runOpsNew: prisma17,
runOpsLegacyReplica: legacySpyA.client,
controlPlaneReplica: prisma14,
splitEnabled: true,
});
const pageA = await presenterA.call(baseCall(ctx14, { pageSize: 2 }));
// new ids are e, c, a -> DESC: e, c (pageSize 2). pageSize+1 = 3 rows from new fills the page.
expect(pageA.batches.map((b) => b.id)).toEqual(["batch_e", "batch_c"]);
expect(legacySpyA.counts.findMany).toBe(0);
// Case B: page needs legacy rows => legacy IS read and the merge is keyset-ordered union.
const legacySpyB = spyClient(prisma14);
const presenterB = new BatchListPresenter(prisma17, prisma17, {
runOpsNew: prisma17,
runOpsLegacyReplica: legacySpyB.client,
controlPlaneReplica: prisma14,
splitEnabled: true,
});
const pageB = await presenterB.call(baseCall(ctx14, { pageSize: 4 }));
// union DESC of all 5: e, d, c, b, a -> first 4.
expect(pageB.batches.map((b) => b.id)).toEqual(["batch_e", "batch_d", "batch_c", "batch_b"]);
expect(legacySpyB.counts.findMany).toBeGreaterThan(0);
// cursor parity: next is the 4th id (pageSize-th), previous undefined (no input cursor).
expect(pageB.pagination.next).toBe("batch_b");
expect(pageB.pagination.previous).toBeUndefined();
expect(pageB.hasAnyBatches).toBe(true);
}
);
// Project resolves on control-plane; no cross-seam join.
heteroPostgresTest(
"project resolves on the control-plane handle (PG14); BatchTaskRun scan reads run-ops only",
async ({ prisma14, prisma17 }) => {
// Project/env/orgMember/user only on PG14 (control-plane). BatchTaskRun env mirrored to PG17.
const ctx = await seedParents(prisma14, "cp");
await mirrorEnvParents(prisma17, ctx, "cp");
await createBatch(prisma17, ctx, { id: "batch_cp1", friendlyId: "fr_cp1", runCount: 7 });
// controlPlaneReplica must never run the BatchTaskRun raw scan.
const cpSpy = spyClient(prisma14, { throwOnQueryRaw: true });
// runOpsNew must never run a project lookup — guard by making project absent on PG17.
const presenter = new BatchListPresenter(prisma17, prisma17, {
runOpsNew: prisma17,
runOpsLegacyReplica: prisma14,
controlPlaneReplica: cpSpy.client,
splitEnabled: true,
});
const page = await presenter.call(baseCall(ctx, { pageSize: 10 }));
expect(page.batches.map((b) => b.id)).toEqual(["batch_cp1"]);
// displayableEnvironment mapped by in-memory id match.
expect(page.batches[0].environment.id).toBe(ctx.environmentId);
expect(page.batches[0].environment.type).toBe("DEVELOPMENT");
// control-plane handle was used (project read) but never for the batch scan.
expect(cpSpy.counts.findMany).toBe(0);
}
);
// Empty-state probe is dual-DB during the window.
heteroPostgresTest(
"empty-state probe reads new then legacy replica: true when legacy has a batch, false when both empty",
async ({ prisma14, prisma17 }) => {
const ctx = await seedParents(prisma14, "probe");
await mirrorEnvParents(prisma17, ctx, "probe");
// Zero batches on new (PG17), one on legacy (PG14). A filter that yields an empty page.
await createBatch(prisma14, ctx, { id: "batch_legacy_only", friendlyId: "fr_legacy_only" });
const presenter = new BatchListPresenter(prisma17, prisma17, {
runOpsNew: prisma17,
runOpsLegacyReplica: prisma14,
controlPlaneReplica: prisma14,
splitEnabled: true,
});
// friendlyId filter that matches nothing => empty page, probe must still find the legacy row.
const page = await presenter.call(baseCall(ctx, { friendlyId: "fr_does_not_exist" }));
expect(page.batches).toHaveLength(0);
expect(page.hasAnyBatches).toBe(true);
// Now wipe legacy too => both empty => hasAnyBatches false.
await prisma14.batchTaskRun.deleteMany({
where: { runtimeEnvironmentId: ctx.environmentId },
});
const page2 = await presenter.call(baseCall(ctx, { friendlyId: "fr_does_not_exist" }));
expect(page2.batches).toHaveLength(0);
expect(page2.hasAnyBatches).toBe(false);
}
);
// Single-DB passthrough collapses to one handle.
postgresTest(
"passthrough (no readRoute): scan + probe + project all read the single handle; legacy closures never invoked",
async ({ prisma }) => {
const ctx = await seedParents(prisma, "pass");
await createBatch(prisma, ctx, { id: "batch_p1", friendlyId: "fr_p1", runCount: 3 });
await createBatch(prisma, ctx, { id: "batch_p2", friendlyId: "fr_p2", runCount: 4 });
await createBatch(prisma, ctx, { id: "batch_p3", friendlyId: "fr_p3", runCount: 5 });
const presenter = new BatchListPresenter(prisma, prisma);
const page = await presenter.call(baseCall(ctx, { pageSize: 2 }));
// Page content + ordering + cursors equal a direct $queryRaw of the same SQL.
const direct = await rawScan(prisma, {
environmentId: ctx.environmentId,
pageSize: 2,
direction: "forward",
});
const hasMore = direct.length > 2;
const expectedPage = direct.slice(0, 2);
expect(page.batches.map((b) => b.id)).toEqual(expectedPage.map((r) => r.id));
expect(page.pagination.next).toBe(hasMore ? expectedPage[1].id : undefined);
expect(page.pagination.previous).toBeUndefined();
expect(page.hasAnyBatches).toBe(true);
// A throwing legacy handle proves the split branch is never entered in passthrough.
const throwingLegacy = spyClient(prisma, { throwOnQueryRaw: true, throwOnFindFirst: true });
const presenterWithUnusedLegacy = new BatchListPresenter(prisma, prisma, {
runOpsLegacyReplica: throwingLegacy.client,
// splitEnabled omitted => passthrough; legacy must never be touched.
});
const page2 = await presenterWithUnusedLegacy.call(baseCall(ctx, { pageSize: 2 }));
expect(page2.batches.map((b) => b.id)).toEqual(expectedPage.map((r) => r.id));
expect(throwingLegacy.counts.findMany).toBe(0);
expect(throwingLegacy.counts.findFirst).toBe(0);
}
);
heteroRunOpsPostgresTest(
"scan against dedicated RunOpsPrismaClient (splitEnabled): returns batches from new DB",
async ({ prisma14, prisma17 }) => {
const ctx = await seedParents(prisma14, "rawscan-batch14");
// runtimeEnvironmentId is a FK-free scalar in the run-ops schema — no parent row needed.
await (prisma17 as RunOpsPrismaClient).batchTaskRun.create({
data: {
id: "rbatch00000000000000001",
friendlyId: "fr_rbatch00000000000000001",
runtimeEnvironmentId: ctx.environmentId,
status: "PENDING",
batchVersion: "v3",
runCount: 2,
},
});
const presenter = new BatchListPresenter(prisma14 as any, prisma14 as any, {
runOpsNew: prisma17 as any,
runOpsLegacyReplica: prisma14 as any,
controlPlaneReplica: prisma14 as any,
splitEnabled: true,
});
const page = await presenter.call(baseCall(ctx, { pageSize: 10 }));
expect(page.batches.map((b) => b.id)).toContain("rbatch00000000000000001");
}
);
});