11// Real heterogeneous legacy + new Postgres proof for the alert-hydration TaskRun read.
2- // The DB is never mocked. A test-only RunStore wraps two real PostgresRunStore
3- // instances and routes findRun by id residency (run-ops id → NEW, cuid → LEGACY),
4- // mirroring the sibling routing suite. The ProjectAlertChannel read must stay control-plane.
2+ // The DB is never mocked. The REAL RoutingRunStore wraps two real PostgresRunStore instances and
3+ // routes findRun by id residency, mirroring the sibling routing suite. The ProjectAlertChannel
4+ // read must stay control-plane.
55//
66// The alert env-type read (parentEnvironment?.type ?? type) is resolved via the app
77// ControlPlaneResolver over a control-plane client DISTINCT from the run-ops store, proving the
88// cross-provider inversion. The prior version co-located env + run and masked it.
99import { heteroPostgresTest , postgresTest } from "@internal/testcontainers" ;
10- import { PostgresRunStore } from "@internal/run-store" ;
11- import type { ReadClient , RunStore } from "@internal/run-store" ;
12- import type { Prisma , PrismaClient } from "@trigger.dev/database" ;
13- import { generateRunOpsId , ownerEngine } from "@trigger.dev/core/v3/isomorphic" ;
10+ import { PostgresRunStore , RoutingRunStore } from "@internal/run-store" ;
11+ import type { PrismaClient } from "@trigger.dev/database" ;
12+ import { generateRunOpsId } from "@trigger.dev/core/v3/isomorphic" ;
1413import { describe , expect } from "vitest" ;
1514import { ControlPlaneCache } from "~/v3/runOpsMigration/controlPlaneCache.server" ;
1615import { ControlPlaneResolver } from "~/v3/runOpsMigration/controlPlaneResolver.server" ;
@@ -28,145 +27,16 @@ function buildControlPlaneResolver(controlPlane: PrismaClient) {
2827
2928vi . setConfig ( { testTimeout : 60_000 } ) ;
3029
31- // Test-only routing store: resolve findRun by id length (27 → NEW, else LEGACY),
32- // dropping any forwarded client so each inner store uses its OWN prisma. NOT a mock —
33- // real DB I/O against two PostgresRunStore instances.
34- class RoutingRunStore implements RunStore {
35- readonly #newStore: PostgresRunStore ;
36- readonly #legacyStore: PostgresRunStore ;
37-
38- constructor ( newStore : PostgresRunStore , legacyStore : PostgresRunStore ) {
39- this . #newStore = newStore ;
40- this . #legacyStore = legacyStore ;
41- }
42-
43- #resolveById( runId : string ) : PostgresRunStore {
44- return ownerEngine ( runId ) === "NEW" ? this . #newStore : this . #legacyStore;
45- }
46-
47- #idFromWhere( where : Prisma . TaskRunWhereInput ) : string | undefined {
48- const id = ( where as { id ?: unknown } ) . id ;
49- return typeof id === "string" ? id : undefined ;
50- }
51-
52- async findRun (
53- where : Prisma . TaskRunWhereInput ,
54- argsOrClient ?: { select ?: Prisma . TaskRunSelect ; include ?: Prisma . TaskRunInclude } | ReadClient ,
55- _client ?: ReadClient
56- ) : Promise < unknown > {
57- const id = this . #idFromWhere( where ) ;
58- if ( id !== undefined ) {
59- return ( this . #resolveById( id ) . findRun as any ) ( where , argsOrClient ) ;
60- }
61- const fromNew = await ( this . #newStore. findRun as any ) ( where , argsOrClient ) ;
62- return fromNew ?? ( this . #legacyStore. findRun as any ) ( where , argsOrClient ) ;
63- }
64-
65- // The remaining RunStore methods are not exercised here; delegate to NEW to satisfy
66- // the interface.
67- findRunOrThrow ( ...a : any [ ] ) : any {
68- return ( this . #newStore. findRunOrThrow as any ) ( ...a ) ;
69- }
70- findRuns ( ...a : any [ ] ) : any {
71- return ( this . #newStore. findRuns as any ) ( ...a ) ;
72- }
73- createRun ( p : any , tx ?: any ) : any {
74- return this . #resolveById( p . data . id ) . createRun ( p , tx ) ;
75- }
76- createCancelledRun ( p : any , tx ?: any ) : any {
77- return this . #resolveById( p . data . id ) . createCancelledRun ( p , tx ) ;
78- }
79- createFailedRun ( p : any , tx ?: any ) : any {
80- return this . #resolveById( p . data . id ) . createFailedRun ( p , tx ) ;
81- }
82- updateMetadata ( runId : string , ...a : any [ ] ) : any {
83- return ( this . #resolveById( runId ) . updateMetadata as any ) ( ...[ runId , ...a ] ) ;
84- }
85- startAttempt ( runId : string , ...a : any [ ] ) : any {
86- return ( this . #resolveById( runId ) . startAttempt as any ) ( runId , ...a ) ;
87- }
88- completeAttemptSuccess ( runId : string , ...a : any [ ] ) : any {
89- return ( this . #resolveById( runId ) . completeAttemptSuccess as any ) ( runId , ...a ) ;
90- }
91- recordRetryOutcome ( runId : string , ...a : any [ ] ) : any {
92- return ( this . #resolveById( runId ) . recordRetryOutcome as any ) ( runId , ...a ) ;
93- }
94- requeueRun ( runId : string , ...a : any [ ] ) : any {
95- return ( this . #resolveById( runId ) . requeueRun as any ) ( runId , ...a ) ;
96- }
97- recordBulkActionMembership ( runId : string , ...a : any [ ] ) : any {
98- return ( this . #resolveById( runId ) . recordBulkActionMembership as any ) ( runId , ...a ) ;
99- }
100- cancelRun ( runId : string , ...a : any [ ] ) : any {
101- return ( this . #resolveById( runId ) . cancelRun as any ) ( runId , ...a ) ;
102- }
103- failRunPermanently ( runId : string , ...a : any [ ] ) : any {
104- return ( this . #resolveById( runId ) . failRunPermanently as any ) ( runId , ...a ) ;
105- }
106- expireRun ( runId : string , ...a : any [ ] ) : any {
107- return ( this . #resolveById( runId ) . expireRun as any ) ( runId , ...a ) ;
108- }
109- expireRunsBatch ( runIds : string [ ] , ...a : any [ ] ) : any {
110- return ( this . #resolveById( runIds [ 0 ] ?? "" ) . expireRunsBatch as any ) ( runIds , ...a ) ;
111- }
112- lockRunToWorker ( runId : string , ...a : any [ ] ) : any {
113- return ( this . #resolveById( runId ) . lockRunToWorker as any ) ( runId , ...a ) ;
114- }
115- parkPendingVersion ( runId : string , ...a : any [ ] ) : any {
116- return ( this . #resolveById( runId ) . parkPendingVersion as any ) ( runId , ...a ) ;
117- }
118- promotePendingVersionRuns ( runId : string , ...a : any [ ] ) : any {
119- return ( this . #resolveById( runId ) . promotePendingVersionRuns as any ) ( runId , ...a ) ;
120- }
121- expireParkedRun ( runId : string , ...a : any [ ] ) : any {
122- return ( this . #resolveById( runId ) . expireParkedRun as any ) ( runId , ...a ) ;
123- }
124- suspendForCheckpoint ( runId : string , ...a : any [ ] ) : any {
125- return ( this . #resolveById( runId ) . suspendForCheckpoint as any ) ( runId , ...a ) ;
126- }
127- resumeFromCheckpoint ( runId : string , ...a : any [ ] ) : any {
128- return ( this . #resolveById( runId ) . resumeFromCheckpoint as any ) ( runId , ...a ) ;
129- }
130- rescheduleRun ( runId : string , ...a : any [ ] ) : any {
131- return ( this . #resolveById( runId ) . rescheduleRun as any ) ( runId , ...a ) ;
132- }
133- enqueueDelayedRun ( runId : string , ...a : any [ ] ) : any {
134- return ( this . #resolveById( runId ) . enqueueDelayedRun as any ) ( runId , ...a ) ;
135- }
136- rewriteDebouncedRun ( runId : string , ...a : any [ ] ) : any {
137- return ( this . #resolveById( runId ) . rewriteDebouncedRun as any ) ( runId , ...a ) ;
138- }
139- clearIdempotencyKey ( params : any , tx ?: any ) : any {
140- const runId = params ?. byId ?. runId ?? "" ;
141- return this . #resolveById( runId ) . clearIdempotencyKey ( params , tx ) ;
142- }
143- pushTags ( runId : string , ...a : any [ ] ) : any {
144- return ( this . #resolveById( runId ) . pushTags as any ) ( runId , ...a ) ;
145- }
146- pushRealtimeStream ( runId : string , ...a : any [ ] ) : any {
147- return ( this . #resolveById( runId ) . pushRealtimeStream as any ) ( runId , ...a ) ;
148- }
149- finalizeRun ( runId : string , ...a : any [ ] ) : any {
150- return ( this . #resolveById( runId ) . finalizeRun as any ) ( runId , ...a ) ;
151- }
152- findManyBatchTaskRunItems ( ...a : any [ ] ) : any {
153- return ( this . #newStore. findManyBatchTaskRunItems as any ) ( ...a ) ;
154- }
155- findBatchTaskRunItem ( ...a : any [ ] ) : any {
156- return ( this . #newStore. findBatchTaskRunItem as any ) ( ...a ) ;
157- }
158- upsertWaitpointTag ( ...a : any [ ] ) : any {
159- return ( this . #newStore. upsertWaitpointTag as any ) ( ...a ) ;
160- }
161- findManyWaitpointTags ( ...a : any [ ] ) : any {
162- return ( this . #newStore. findManyWaitpointTags as any ) ( ...a ) ;
163- }
164- }
30+ // The alert-hydration TaskRun read runs through the REAL RoutingRunStore over two real
31+ // PostgresRunStore instances (NEW = PG17, LEGACY = PG14). The DB is never mocked. The router
32+ // resolves residency from the id shape — a v1 run-ops id (26 chars, version "1" at index 25) to
33+ // NEW, a 25-char cuid to LEGACY — and never forwards a caller-passed control-plane client into a
34+ // routed read, so each store uses its OWN prisma.
16535
16636function buildRoutingStore ( prisma17 : PrismaClient , prisma14 : PrismaClient ) {
16737 const newStore = new PostgresRunStore ( { prisma : prisma17 , readOnlyPrisma : prisma17 } ) ;
16838 const legacyStore = new PostgresRunStore ( { prisma : prisma14 , readOnlyPrisma : prisma14 } ) ;
169- return new RoutingRunStore ( newStore , legacyStore ) ;
39+ return new RoutingRunStore ( { new : newStore , legacy : legacyStore } ) ;
17040}
17141
17242async function seedProject ( prisma : PrismaClient , suffix : string ) {
0 commit comments