Skip to content

Commit bf8f7c8

Browse files
d-csclaude
andcommitted
refactor(run-ops): drop known-migrated from write-path + read repos; id-shape only
Migration is deferred, so child/batch residency is a pure id-shape check. Remove the isKnownMigrated (and mint-only isSplitEnabled) deps from the mint sites (triggerTask, triggerFailedTask, batchTriggerV3) and call the now- synchronous resolveInheritedMintKind(parentFriendlyId) with no deps arg. Read paths: drop the isKnownMigrated re-probe-avoidance from the ClickHouse runs hydrate (probe all missing on legacy), the runsRepository readThrough options type, resolveWaitpointThroughReadThrough deps, and the BulkActionV2 batch seam adapter — keeping the genuine cross-seam fallback that reads NEW first for unclassifiable/legacy-candidate ids. Delete the injected-marker test cases; the remaining residency tests assert pure id-shape inheritance. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 9535ae6 commit bf8f7c8

16 files changed

Lines changed: 80 additions & 547 deletions

apps/webapp/app/runEngine/concerns/resolveWaitpointThroughReadThrough.server.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import type { PrismaReplicaClient } from "~/db.server";
22
import { $replica } from "~/db.server";
33
import { readThroughRun } from "~/v3/runOpsMigration/readThrough.server";
4-
import { isKnownMigrated as defaultIsKnownMigrated } from "~/v3/runOpsMigration/knownMigratedFilter.server";
54

65
type ResolveWaitpointDeps = {
76
newClient?: PrismaReplicaClient;
87
legacyReplica?: PrismaReplicaClient;
98
splitEnabled?: boolean;
10-
isKnownMigrated?: (id: string) => Promise<boolean>;
119
isPastRetention?: (id: string) => boolean;
1210
};
1311

@@ -26,7 +24,6 @@ export async function resolveWaitpointThroughReadThrough<T>(opts: {
2624
splitEnabled: opts.deps?.splitEnabled,
2725
newClient: opts.deps?.newClient ?? $replica,
2826
legacyReplica: opts.deps?.legacyReplica ?? $replica,
29-
isKnownMigrated: opts.deps?.isKnownMigrated ?? defaultIsKnownMigrated,
3027
isPastRetention: opts.deps?.isPastRetention,
3128
},
3229
});

apps/webapp/app/runEngine/services/triggerFailedTask.server.ts

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ import type { PrismaClientOrTransaction } from "@trigger.dev/database";
66
import type { AuthenticatedEnvironment } from "~/services/apiAuth.server";
77
import { logger } from "~/services/logger.server";
88
import { resolveRunIdMintKind } from "~/v3/engineVersion.server";
9-
import { isKnownMigrated as defaultIsKnownMigrated } from "~/v3/runOpsMigration/knownMigratedFilter.server";
10-
import { isSplitEnabled as defaultIsSplitEnabled } from "~/v3/runOpsMigration/splitMode.server";
119
import { resolveInheritedMintKind } from "~/v3/runOpsMigration/resolveInheritedMintKind.server";
1210
import { getEventRepository } from "~/v3/eventRepository/index.server";
1311
import { PerformTaskRunAlertsService } from "~/v3/services/alerts/performTaskRunAlerts.server";
@@ -60,12 +58,6 @@ export class TriggerFailedTaskService {
6058
private readonly prisma: PrismaClientOrTransaction;
6159
private readonly replicaPrisma: PrismaClientOrTransaction;
6260
private readonly engine: RunEngine;
63-
// Reports whether a run that is legacy by id-shape has already been moved to
64-
// the new store. Injected for tests; defaults to the live resolver.
65-
private readonly isKnownMigrated: (runId: string) => Promise<boolean>;
66-
// Injected so the migrated-marker read stays off the hot path when split is off
67-
// (same guard as RunEngineTriggerTaskService); defaults to the live resolver.
68-
private readonly isSplitEnabled: () => Promise<boolean>;
6961
// Resolves the parent run for depth/root/parent linkage. Defaults to the shared
7062
// singleton (in production the same store the engine writes through). Injected in
7163
// tests so the read resolves on the same store the engine wrote to.
@@ -75,15 +67,11 @@ export class TriggerFailedTaskService {
7567
prisma: PrismaClientOrTransaction;
7668
engine: RunEngine;
7769
replicaPrisma?: PrismaClientOrTransaction;
78-
isKnownMigrated?: (runId: string) => Promise<boolean>;
79-
isSplitEnabled?: () => Promise<boolean>;
8070
runStore?: RunStore;
8171
}) {
8272
this.prisma = opts.prisma;
8373
this.replicaPrisma = opts.replicaPrisma ?? opts.prisma;
8474
this.engine = opts.engine;
85-
this.isKnownMigrated = opts.isKnownMigrated ?? defaultIsKnownMigrated;
86-
this.isSplitEnabled = opts.isSplitEnabled ?? defaultIsSplitEnabled;
8775
this.runStore = opts.runStore ?? defaultRunStore;
8876
}
8977

@@ -98,10 +86,7 @@ export class TriggerFailedTaskService {
9886
parentRunFriendlyId?: string;
9987
}): Promise<string> {
10088
const mintKind = args.parentRunFriendlyId
101-
? await resolveInheritedMintKind(args.parentRunFriendlyId, {
102-
isSplitEnabled: this.isSplitEnabled,
103-
isKnownMigrated: this.isKnownMigrated,
104-
})
89+
? resolveInheritedMintKind(args.parentRunFriendlyId)
10590
: await resolveRunIdMintKind({
10691
organizationId: args.organizationId,
10792
id: args.environmentId,

apps/webapp/app/runEngine/services/triggerTask.server.test.ts

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -207,9 +207,6 @@ describe("RunEngineTriggerTaskService parent + locked-worker reads", () => {
207207
traceEventConcern: new MockTraceEventConcern(),
208208
tracer: trace.getTracer("test", "0.0.0"),
209209
metadataMaximumSize: 1024 * 1024 * 1,
210-
// Keep the migrated-parent resolver from reaching the empty ~/db.server
211-
// mock; mint-kind inheritance is not under test here.
212-
isKnownMigrated: async () => false,
213210
});
214211

215212
// Trigger a ROOT run first to create a real parent TaskRun.
@@ -312,7 +309,6 @@ describe("RunEngineTriggerTaskService parent + locked-worker reads", () => {
312309
traceEventConcern: new MockTraceEventConcern(),
313310
tracer: trace.getTracer("test", "0.0.0"),
314311
metadataMaximumSize: 1024 * 1024 * 1,
315-
isKnownMigrated: async () => false,
316312
});
317313

318314
// A real parent run in envA.
@@ -415,7 +411,6 @@ describe("RunEngineTriggerTaskService parent + locked-worker reads", () => {
415411
traceEventConcern: new MockTraceEventConcern(),
416412
tracer: trace.getTracer("test", "0.0.0"),
417413
metadataMaximumSize: 1024 * 1024 * 1,
418-
isKnownMigrated: async () => false,
419414
});
420415

421416
const result = await triggerTaskService.call({
@@ -533,7 +528,6 @@ describe("RunEngineTriggerTaskService parent + locked-worker reads", () => {
533528
traceEventConcern: new MockTraceEventConcern(),
534529
tracer: trace.getTracer("test", "0.0.0"),
535530
metadataMaximumSize: 1024 * 1024 * 1,
536-
isKnownMigrated: async () => false,
537531
});
538532

539533
// ROOT parent first (uses the unproxied prisma via a separate service so
@@ -552,7 +546,6 @@ describe("RunEngineTriggerTaskService parent + locked-worker reads", () => {
552546
traceEventConcern: new MockTraceEventConcern(),
553547
tracer: trace.getTracer("test", "0.0.0"),
554548
metadataMaximumSize: 1024 * 1024 * 1,
555-
isKnownMigrated: async () => false,
556549
});
557550
const parentResult = await parentService.call({
558551
taskId: taskIdentifier,
@@ -655,7 +648,6 @@ describe("RunEngineTriggerTaskService parent + locked-worker reads", () => {
655648
traceEventConcern: new MockTraceEventConcern(),
656649
tracer: trace.getTracer("test", "0.0.0"),
657650
metadataMaximumSize: 1024 * 1024 * 1,
658-
isKnownMigrated: async () => false,
659651
});
660652

661653
const bogusVersion = "v-does-not-exist-0000";
@@ -757,7 +749,6 @@ describe("RunEngineTriggerTaskService parent + locked-worker reads", () => {
757749
traceEventConcern: new MockTraceEventConcern(),
758750
tracer: trace.getTracer("test", "0.0.0"),
759751
metadataMaximumSize: 1024 * 1024 * 1,
760-
isKnownMigrated: async () => false,
761752
});
762753

763754
// Trigger in envB locking to the shared version string.
@@ -799,12 +790,15 @@ describe("RunEngineTriggerTaskService parent + locked-worker reads", () => {
799790
prisma,
800791
payloadProcessor: new MockPayloadProcessor(),
801792
queueConcern: new DefaultQueueManager(prisma, engine),
802-
idempotencyKeyConcern: new IdempotencyKeyConcern(prisma, engine, new MockTraceEventConcern()),
793+
idempotencyKeyConcern: new IdempotencyKeyConcern(
794+
prisma,
795+
engine,
796+
new MockTraceEventConcern()
797+
),
803798
validator,
804799
traceEventConcern: new MockTraceEventConcern(),
805800
tracer: trace.getTracer("test", "0.0.0"),
806801
metadataMaximumSize: 1024 * 1024 * 1,
807-
isKnownMigrated: async () => false,
808802
});
809803

810804
// Trigger with NO parentRunId.

apps/webapp/app/runEngine/services/triggerTask.server.ts

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ import { parseDelay } from "~/utils/delays";
2727
import { handleMetadataPacket } from "~/utils/packets";
2828
import { startSpan } from "~/v3/tracing.server";
2929
import { resolveRunIdMintKind } from "~/v3/engineVersion.server";
30-
import { isKnownMigrated as defaultIsKnownMigrated } from "~/v3/runOpsMigration/knownMigratedFilter.server";
31-
import { isSplitEnabled as defaultIsSplitEnabled } from "~/v3/runOpsMigration/splitMode.server";
3230
import { resolveInheritedMintKind } from "~/v3/runOpsMigration/resolveInheritedMintKind.server";
3331
import type {
3432
TriggerTaskServiceOptions,
@@ -96,14 +94,6 @@ export class RunEngineTriggerTaskService {
9694
private readonly evaluateGate: MollifierEvaluateGate;
9795
private readonly getMollifierBuffer: MollifierGetBuffer;
9896
private readonly isMollifierGloballyEnabled: () => boolean;
99-
// Resolves whether a run that classifies as legacy-by-id-shape has already
100-
// been moved to the new store. Injected so tests can drive the migrated-parent
101-
// case without the split-store infrastructure; defaults to the live resolver.
102-
private readonly isKnownMigrated: (runId: string) => Promise<boolean>;
103-
// Gates whether the marker-aware inheritance branch runs. With split OFF the
104-
// child residency is a pure id-shape check — zero I/O on the hot path,
105-
// byte-identical to today. Injected so tests can drive split on/off.
106-
private readonly isSplitEnabled: () => Promise<boolean>;
10797

10898
constructor(opts: {
10999
prisma: PrismaClientOrTransaction;
@@ -119,8 +109,6 @@ export class RunEngineTriggerTaskService {
119109
evaluateGate?: MollifierEvaluateGate;
120110
getMollifierBuffer?: MollifierGetBuffer;
121111
isMollifierGloballyEnabled?: () => boolean;
122-
isKnownMigrated?: (runId: string) => Promise<boolean>;
123-
isSplitEnabled?: () => Promise<boolean>;
124112
}) {
125113
this.prisma = opts.prisma;
126114
this.engine = opts.engine;
@@ -136,28 +124,22 @@ export class RunEngineTriggerTaskService {
136124
this.getMollifierBuffer = opts.getMollifierBuffer ?? defaultGetMollifierBuffer;
137125
this.isMollifierGloballyEnabled =
138126
opts.isMollifierGloballyEnabled ?? (() => env.TRIGGER_MOLLIFIER_ENABLED === "1");
139-
this.isKnownMigrated = opts.isKnownMigrated ?? defaultIsKnownMigrated;
140-
this.isSplitEnabled = opts.isSplitEnabled ?? defaultIsSplitEnabled;
141127
}
142128

143129
// Mint a new run's friendlyId. The id-kind decides which store the run is born
144130
// in (cuid → legacy store, ksuid → new store), so the whole subgraph of a run
145131
// must agree. Two cases:
146132
//
147133
// - ROOT run (no parent): mint by the environment's cutover setting.
148-
// - CHILD run (has a parent): inherit the parent's CURRENT residency, so a
149-
// parent and child never split across stores. A parent that is legacy by
150-
// id-shape but has already been moved to the new store (reported by the
151-
// migrated check) yields a new-store (ksuid) child.
134+
// - CHILD run (has a parent): inherit the parent's residency by id-shape, so a
135+
// parent and child never split across stores (ksuid parent → ksuid child,
136+
// cuid parent → cuid child).
152137
private async mintRunFriendlyId(
153138
environment: AuthenticatedEnvironment,
154139
parentRunFriendlyId?: string
155140
): Promise<string> {
156141
const mintKind = parentRunFriendlyId
157-
? await resolveInheritedMintKind(parentRunFriendlyId, {
158-
isSplitEnabled: this.isSplitEnabled,
159-
isKnownMigrated: this.isKnownMigrated,
160-
})
142+
? resolveInheritedMintKind(parentRunFriendlyId)
161143
: await resolveRunIdMintKind({
162144
organizationId: environment.organizationId,
163145
id: environment.id,

apps/webapp/app/services/runsRepository/clickhouseRunsRepository.server.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import parseDuration from "parse-duration";
1414
import { decodeRunsCursor, encodeRunsCursor } from "./runsCursor.server";
1515
import { runStore } from "~/v3/runStore.server";
1616
import { type PrismaClientOrTransaction } from "~/db.server";
17-
import { isKnownMigrated as defaultIsKnownMigrated } from "~/v3/runOpsMigration/knownMigratedFilter.server";
1817

1918
type RunCursorRow = { runId: string; createdAt: number };
2019

@@ -181,18 +180,13 @@ export class ClickHouseRunsRepository implements IRunsRepository {
181180
} else {
182181
const newClient = this.options.readThrough?.newClient ?? this.options.prisma;
183182
const legacyReplica = this.options.readThrough?.legacyReplica ?? this.options.prisma;
184-
const isKnownMigrated = this.options.readThrough?.isKnownMigrated ?? defaultIsKnownMigrated;
185183

186184
const newRows = await hydrate(newClient, runIds);
187185
const foundIds = new Set(newRows.map((r) => r.id));
188186
const missing = runIds.filter((id) => !foundIds.has(id));
189187

190-
const toProbeLegacy: string[] = [];
191-
for (const id of missing) {
192-
if (!(await isKnownMigrated(id))) {
193-
toProbeLegacy.push(id);
194-
}
195-
}
188+
// Any id not hydrated from the new store is probed on the legacy replica.
189+
const toProbeLegacy = missing;
196190

197191
const legacyRows = toProbeLegacy.length ? await hydrate(legacyReplica, toProbeLegacy) : [];
198192
rows = [...newRows, ...legacyRows];

apps/webapp/app/services/runsRepository/runsRepository.server.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ export type RunsRepositoryOptions = {
3232
legacyReplica?: PrismaClientOrTransaction;
3333
// Resolved boot constant; when false the split branch is never entered.
3434
splitEnabled?: boolean;
35-
isKnownMigrated?: (runId: string) => Promise<boolean>;
3635
};
3736
};
3837

apps/webapp/app/v3/services/batchTriggerV3.server.ts

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ import { logger } from "~/services/logger.server";
2626
import { getEntitlement } from "~/services/platform.v3.server";
2727
import { controlPlaneResolver } from "~/v3/runOpsMigration/controlPlaneResolver.server";
2828
import { resolveRunIdMintKind, type RunIdMintKind } from "~/v3/engineVersion.server";
29-
import { isKnownMigrated as defaultIsKnownMigrated } from "~/v3/runOpsMigration/knownMigratedFilter.server";
30-
import { isSplitEnabled as defaultIsSplitEnabled } from "~/v3/runOpsMigration/splitMode.server";
3129
import { resolveInheritedMintKind } from "~/v3/runOpsMigration/resolveInheritedMintKind.server";
3230
import { mintBatchFriendlyId } from "~/v3/runOpsMigration/mintBatchFriendlyId.server";
3331
import { batchTriggerWorker } from "../batchTriggerWorker.server";
@@ -113,20 +111,13 @@ export class BatchTriggerV3Service extends BaseService {
113111
asyncBatchProcessSizeThreshold: number = ASYNC_BATCH_PROCESS_SIZE_THRESHOLD,
114112
protected readonly _prisma: PrismaClientOrTransaction = prisma,
115113
protected readonly runStore: RunStore = defaultRunStore,
116-
// Injected so tests drive the migrated-parent branch without the split-store
117-
// infrastructure; defaults to the live resolver (same pattern as
118-
// RunEngineTriggerTaskService).
119-
private readonly isKnownMigrated: (runId: string) => Promise<boolean> = defaultIsKnownMigrated,
120114
// Injected so tests force the env-default branch deterministically; defaults
121115
// to the live per-env mint resolver.
122116
private readonly resolveMintKind: (environment: {
123117
organizationId: string;
124118
id: string;
125119
orgFeatureFlags?: unknown;
126-
}) => Promise<RunIdMintKind> = resolveRunIdMintKind,
127-
// Injected so the migrated-marker read stays off the hot path when split is off
128-
// (same guard as RunEngineTriggerTaskService); defaults to the live resolver.
129-
private readonly isSplitEnabled: () => Promise<boolean> = defaultIsSplitEnabled
120+
}) => Promise<RunIdMintKind> = resolveRunIdMintKind
130121
) {
131122
super(_prisma);
132123

@@ -355,19 +346,15 @@ export class BatchTriggerV3Service extends BaseService {
355346

356347
// Mint a child run's friendlyId so it lands in the SAME physical store as its
357348
// residency anchor. The caller passes the batch's friendlyId, so a ksuid
358-
// anchor (or a cuid-shaped one already migrated to the new store) yields a ksuid
359-
// (NEW) child and a cuid anchor yields a cuid (LEGACY) child. With no anchor it
360-
// falls back to the env's cutover setting. Mirrors
361-
// RunEngineTriggerTaskService.mintRunFriendlyId.
349+
// (NEW) anchor yields a ksuid (NEW) child and a cuid anchor yields a cuid
350+
// (LEGACY) child. With no anchor it falls back to the env's cutover setting.
351+
// Mirrors RunEngineTriggerTaskService.mintRunFriendlyId.
362352
private async mintChildFriendlyId(
363353
environment: AuthenticatedEnvironment,
364354
anchorFriendlyId?: string
365355
): Promise<string> {
366356
const mintKind = anchorFriendlyId
367-
? await resolveInheritedMintKind(anchorFriendlyId, {
368-
isSplitEnabled: this.isSplitEnabled,
369-
isKnownMigrated: this.isKnownMigrated,
370-
})
357+
? resolveInheritedMintKind(anchorFriendlyId)
371358
: await this.resolveMintKind({
372359
organizationId: environment.organizationId,
373360
id: environment.id,

apps/webapp/app/v3/services/bulk/BulkActionV2.batchReadThrough.server.test.ts

Lines changed: 3 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
// Real PG14 (legacy replica) + PG17 (new) proof for the bulk batch read-through adapter.
22
// We NEVER mock the DB: each closure runs a real `$queryRaw` against the passed container
33
// (crossing the actual PG14↔PG17 boundary) then filters an in-memory seeded set by id —
4-
// mirroring readThrough.server.test.ts's `realRead`. The only injected fakes are the pure
5-
// boundaries the plan allows (`isKnownMigrated`) plus throwing spies asserting a store was
6-
// NEVER touched.
4+
// mirroring readThrough.server.test.ts's `realRead`. The only injected fakes are throwing
5+
// spies asserting a store was NEVER touched.
76
import { heteroPostgresTest } from "@internal/testcontainers";
87
import { describe, expect, vi } from "vitest";
98
import type { PrismaReplicaClient } from "~/db.server";
@@ -51,7 +50,6 @@ describe("hydrateRunsAcrossSeam (PG14 legacy replica + PG17 new)", () => {
5150
splitEnabled: true,
5251
newClient: prisma17 as unknown as PrismaReplicaClient,
5352
legacyReplica: prisma14 as unknown as PrismaReplicaClient,
54-
isKnownMigrated: async () => false,
5553
},
5654
});
5755

@@ -64,40 +62,12 @@ describe("hydrateRunsAcrossSeam (PG14 legacy replica + PG17 new)", () => {
6462
);
6563

6664
heteroPostgresTest(
67-
"(b) known-migrated short-circuit: legacy-classified id missed by new is not probed and is omitted",
68-
async ({ prisma14, prisma17 }) => {
69-
const onNew = new Set<string>(); // new misses it
70-
const throwingLegacy = vi.fn(async (): Promise<Row[]> => {
71-
throw new Error("readLegacyReplica must never run for a known-migrated id");
72-
});
73-
74-
const rows = await hydrateRunsAcrossSeam<Row>({
75-
runIds: [LEGACY_RUN_ID],
76-
readNew: (client, ids) => realReadFiltered(client, ids, onNew),
77-
readLegacyReplica: throwingLegacy,
78-
deps: {
79-
splitEnabled: true,
80-
newClient: prisma17 as unknown as PrismaReplicaClient,
81-
legacyReplica: prisma14 as unknown as PrismaReplicaClient,
82-
isKnownMigrated: async () => true,
83-
},
84-
});
85-
86-
expect(rows).toEqual([]);
87-
expect(throwingLegacy).not.toHaveBeenCalled();
88-
}
89-
);
90-
91-
heteroPostgresTest(
92-
"(c) passthrough: splitEnabled false reads only the single client; legacy + filter never touched",
65+
"(c) passthrough: splitEnabled false reads only the single client; legacy never touched",
9366
async ({ prisma14, prisma17 }) => {
9467
const onNew = new Set([NEW_RUN_ID, LEGACY_RUN_ID]);
9568
const throwingLegacy = vi.fn(async (): Promise<Row[]> => {
9669
throw new Error("readLegacyReplica must never run in single-DB mode");
9770
});
98-
const throwingFilter = vi.fn(async (): Promise<boolean> => {
99-
throw new Error("isKnownMigrated must never run in single-DB mode");
100-
});
10171
const readNew = vi.fn((client: PrismaReplicaClient, ids: string[]) =>
10272
realReadFiltered(client, ids, onNew)
10373
);
@@ -111,15 +81,13 @@ describe("hydrateRunsAcrossSeam (PG14 legacy replica + PG17 new)", () => {
11181
// single collapsed store (use prisma17 here as the "new"/primary analog)
11282
newClient: prisma17 as unknown as PrismaReplicaClient,
11383
legacyReplica: prisma14 as unknown as PrismaReplicaClient,
114-
isKnownMigrated: throwingFilter,
11584
},
11685
});
11786

11887
const ids = rows.map((r) => r.id).sort();
11988
expect(ids).toEqual([LEGACY_RUN_ID, NEW_RUN_ID].sort());
12089
expect(readNew).toHaveBeenCalledTimes(1);
12190
expect(throwingLegacy).not.toHaveBeenCalled();
122-
expect(throwingFilter).not.toHaveBeenCalled();
12391
}
12492
);
12593
});

0 commit comments

Comments
 (0)