11// The resolver must produce what the executor already consumes, so the oracle is the
22// existing hydration and not a hand-written literal. A literal cannot catch a drift in
33// enhanceExecutionSnapshotWithWaitpoints itself; this can.
4- import type { Waitpoint } from "@trigger.dev/database" ;
5- import { describe , expect , it } from "vitest" ;
4+ import { postgresTest } from "@internal/testcontainers" ;
5+ import { PostgresRunStore } from "@internal/run-store" ;
6+ import type { PrismaClient , Waitpoint } from "@trigger.dev/database" ;
7+ import { describe , expect } from "vitest" ;
8+ import { seedChildRunWithOutput } from "./testFixtures/childRun.js" ;
69import { enhanceExecutionSnapshotWithWaitpoints } from "../systems/executionSnapshotSystem.js" ;
710import { buildCompletedWaitpointRecords } from "./completedWaitpointRecords.js" ;
8- import { createCompletedWaitpointResolver } from "./completedWaitpointResolver.js" ;
11+ import {
12+ createCompletedWaitpointResolver ,
13+ createRunOutputReader ,
14+ } from "./completedWaitpointResolver.js" ;
915import { envelopeSourceFromWaitpointRow } from "./completionEnvelopeSource.js" ;
1016import type { CompletionEnvelopeSource } from "./types.js" ;
1117
1218const COMPLETED_AT = new Date ( "2026-08-25T00:00:00.000Z" ) ;
1319const RUN_ID = "run_0123456789abcdefghijklm" ;
14- const CHILD_RUN_ID = "run_zyxwvutsrqponmlkjihgfe" ;
1520const BATCH_ID = "batch_0123456789abcdefghijk" ;
1621
1722/**
@@ -70,25 +75,21 @@ function sortEntries<T extends { id: string; index?: number }>(entries: T[]): T[
7075 * variant makes — that TaskRun.output holds the same string.
7176 */
7277async function bothPaths (
78+ prisma : PrismaClient ,
7379 pairs : ReturnType < typeof pair > [ ] ,
7480 order : string [ ] ,
7581 batchId : string | null = null
7682) {
77- const outputsByRunId = new Map < string , string > ( ) ;
78- for ( const { row } of pairs ) {
79- if ( row . completedByTaskRunId && row . output !== null ) {
80- outputsByRunId . set ( row . completedByTaskRunId , row . output ) ;
81- }
82- }
83-
8483 const expected = enhanceExecutionSnapshotWithWaitpoints (
8584 snapshot ( batchId ) ,
8685 pairs . map ( ( p ) => p . row ) ,
8786 order
8887 ) . completedWaitpoints ;
8988
89+ const runStore = new PostgresRunStore ( { prisma, readOnlyPrisma : prisma } ) ;
90+
9091 const actual = await createCompletedWaitpointResolver ( {
91- readRunOutput : async ( taskRunId ) => outputsByRunId . get ( taskRunId ) ,
92+ readRunOutput : createRunOutputReader ( runStore ) ,
9293 } ) ( {
9394 runId : RUN_ID ,
9495 ...( batchId ? { batchId } : { } ) ,
@@ -102,54 +103,64 @@ async function bothPaths(
102103}
103104
104105describe ( "the resolver reproduces the existing hydration" , ( ) => {
105- it ( "for a single MANUAL waitpoint with an inline output" , async ( ) => {
106+ postgresTest ( "for a single MANUAL waitpoint with an inline output" , async ( { prisma } ) => {
106107 const { expected, actual } = await bothPaths (
108+ prisma ,
107109 [ pair ( { id : "wp_manual" , type : "MANUAL" , output : '{"token":1}' } ) ] ,
108110 [ ]
109111 ) ;
110112
111113 expect ( actual ) . toEqual ( expected ) ;
112114 } ) ;
113115
114- it ( "for a MANUAL waitpoint with a user-provided idempotency key" , async ( ) => {
115- const { expected, actual } = await bothPaths (
116- [
117- pair ( {
118- id : "wp_manual" ,
119- type : "MANUAL" ,
120- output : '{"token":1}' ,
121- idempotencyKey : "user-key" ,
122- userProvidedIdempotencyKey : true ,
123- } ) ,
124- ] ,
125- [ ]
126- ) ;
127-
128- expect ( actual ) . toEqual ( expected ) ;
129- expect ( actual [ 0 ] ?. idempotencyKey ) . toBe ( "user-key" ) ;
130- } ) ;
131-
132- it ( "for an idempotency key the user provided but that went inactive" , async ( ) => {
133- const { expected, actual } = await bothPaths (
134- [
135- pair ( {
136- id : "wp_manual" ,
137- type : "MANUAL" ,
138- output : '{"token":1}' ,
139- idempotencyKey : "user-key" ,
140- userProvidedIdempotencyKey : true ,
141- inactiveIdempotencyKey : "old" ,
142- } ) ,
143- ] ,
144- [ ]
145- ) ;
146-
147- expect ( actual ) . toEqual ( expected ) ;
148- expect ( actual [ 0 ] ?. idempotencyKey ) . toBeUndefined ( ) ;
149- } ) ;
116+ postgresTest (
117+ "for a MANUAL waitpoint with a user-provided idempotency key" ,
118+ async ( { prisma } ) => {
119+ const { expected, actual } = await bothPaths (
120+ prisma ,
121+ [
122+ pair ( {
123+ id : "wp_manual" ,
124+ type : "MANUAL" ,
125+ output : '{"token":1}' ,
126+ idempotencyKey : "user-key" ,
127+ userProvidedIdempotencyKey : true ,
128+ } ) ,
129+ ] ,
130+ [ ]
131+ ) ;
132+
133+ expect ( actual ) . toEqual ( expected ) ;
134+ expect ( actual [ 0 ] ?. idempotencyKey ) . toBe ( "user-key" ) ;
135+ }
136+ ) ;
137+
138+ postgresTest (
139+ "for an idempotency key the user provided but that went inactive" ,
140+ async ( { prisma } ) => {
141+ const { expected, actual } = await bothPaths (
142+ prisma ,
143+ [
144+ pair ( {
145+ id : "wp_manual" ,
146+ type : "MANUAL" ,
147+ output : '{"token":1}' ,
148+ idempotencyKey : "user-key" ,
149+ userProvidedIdempotencyKey : true ,
150+ inactiveIdempotencyKey : "old" ,
151+ } ) ,
152+ ] ,
153+ [ ]
154+ ) ;
155+
156+ expect ( actual ) . toEqual ( expected ) ;
157+ expect ( actual [ 0 ] ?. idempotencyKey ) . toBeUndefined ( ) ;
158+ }
159+ ) ;
150160
151- it ( "for a DATETIME waitpoint" , async ( ) => {
161+ postgresTest ( "for a DATETIME waitpoint" , async ( { prisma } ) => {
152162 const { expected, actual } = await bothPaths (
163+ prisma ,
153164 [
154165 pair ( {
155166 id : "wp_datetime" ,
@@ -163,14 +174,16 @@ describe("the resolver reproduces the existing hydration", () => {
163174 expect ( actual ) . toEqual ( expected ) ;
164175 } ) ;
165176
166- it ( "for a RUN waitpoint outside a batch" , async ( ) => {
177+ postgresTest ( "for a RUN waitpoint outside a batch" , async ( { prisma } ) => {
178+ const childRunId = await seedChildRunWithOutput ( prisma , '{"ok":true}' ) ;
167179 const { expected, actual } = await bothPaths (
180+ prisma ,
168181 [
169182 pair ( {
170183 id : "wp_run" ,
171184 type : "RUN" ,
172185 output : '{"ok":true}' ,
173- completedByTaskRunId : CHILD_RUN_ID ,
186+ completedByTaskRunId : childRunId ,
174187 } ) ,
175188 ] ,
176189 [ ]
@@ -179,14 +192,16 @@ describe("the resolver reproduces the existing hydration", () => {
179192 expect ( actual ) . toEqual ( expected ) ;
180193 } ) ;
181194
182- it ( "for a RUN waitpoint read under a batch" , async ( ) => {
195+ postgresTest ( "for a RUN waitpoint read under a batch" , async ( { prisma } ) => {
196+ const childRunId = await seedChildRunWithOutput ( prisma , '{"ok":true}' ) ;
183197 const { expected, actual } = await bothPaths (
198+ prisma ,
184199 [
185200 pair ( {
186201 id : "wp_run" ,
187202 type : "RUN" ,
188203 output : '{"ok":true}' ,
189- completedByTaskRunId : CHILD_RUN_ID ,
204+ completedByTaskRunId : childRunId ,
190205 } ) ,
191206 ] ,
192207 [ "wp_run" ] ,
@@ -197,15 +212,17 @@ describe("the resolver reproduces the existing hydration", () => {
197212 expect ( actual [ 0 ] ?. completedByTaskRun ?. batch ?. id ) . toBe ( BATCH_ID ) ;
198213 } ) ;
199214
200- it ( "for a RUN waitpoint whose output is an error" , async ( ) => {
215+ postgresTest ( "for a RUN waitpoint whose output is an error" , async ( { prisma } ) => {
216+ const childRunId = await seedChildRunWithOutput ( prisma , '{"message":"boom"}' ) ;
201217 const { expected, actual } = await bothPaths (
218+ prisma ,
202219 [
203220 pair ( {
204221 id : "wp_run" ,
205222 type : "RUN" ,
206223 output : '{"message":"boom"}' ,
207224 outputIsError : true ,
208- completedByTaskRunId : CHILD_RUN_ID ,
225+ completedByTaskRunId : childRunId ,
209226 } ) ,
210227 ] ,
211228 [ ]
@@ -214,17 +231,19 @@ describe("the resolver reproduces the existing hydration", () => {
214231 expect ( actual ) . toEqual ( expected ) ;
215232 } ) ;
216233
217- it ( "for a BATCH waitpoint" , async ( ) => {
234+ postgresTest ( "for a BATCH waitpoint" , async ( { prisma } ) => {
218235 const { expected, actual } = await bothPaths (
236+ prisma ,
219237 [ pair ( { id : "wp_batch" , type : "BATCH" , completedByBatchId : BATCH_ID } ) ] ,
220238 [ ]
221239 ) ;
222240
223241 expect ( actual ) . toEqual ( expected ) ;
224242 } ) ;
225243
226- it ( "for an already-offloaded output" , async ( ) => {
244+ postgresTest ( "for an already-offloaded output" , async ( { prisma } ) => {
227245 const { expected, actual } = await bothPaths (
246+ prisma ,
228247 [
229248 pair ( {
230249 id : "wp_manual" ,
@@ -241,15 +260,17 @@ describe("the resolver reproduces the existing hydration", () => {
241260
242261 // The case the suite was blind to, and the one the frozen reference orders the other way. The
243262 // oracle emits the ref string; so does this, by a different branch.
244- it ( "for an offloaded RUN success" , async ( ) => {
263+ postgresTest ( "for an offloaded RUN success" , async ( { prisma } ) => {
264+ const childRunId = await seedChildRunWithOutput ( prisma , "s3://bucket/key" ) ;
245265 const { expected, actual } = await bothPaths (
266+ prisma ,
246267 [
247268 pair ( {
248269 id : "wp_run_ref" ,
249270 type : "RUN" ,
250271 output : "s3://bucket/key" ,
251272 outputType : "application/store" ,
252- completedByTaskRunId : CHILD_RUN_ID ,
273+ completedByTaskRunId : childRunId ,
253274 } ) ,
254275 ] ,
255276 [ ]
@@ -259,14 +280,16 @@ describe("the resolver reproduces the existing hydration", () => {
259280 expect ( actual [ 0 ] ?. output ) . toBe ( "s3://bucket/key" ) ;
260281 } ) ;
261282
262- it ( "for one run present at two batch indexes" , async ( ) => {
283+ postgresTest ( "for one run present at two batch indexes" , async ( { prisma } ) => {
284+ const childRunId = await seedChildRunWithOutput ( prisma , '{"ok":true}' ) ;
263285 const { expected, actual } = await bothPaths (
286+ prisma ,
264287 [
265288 pair ( {
266289 id : "wp_run" ,
267290 type : "RUN" ,
268291 output : '{"ok":true}' ,
269- completedByTaskRunId : CHILD_RUN_ID ,
292+ completedByTaskRunId : childRunId ,
270293 } ) ,
271294 ] ,
272295 [ "wp_run" , "wp_run" ] ,
@@ -277,15 +300,19 @@ describe("the resolver reproduces the existing hydration", () => {
277300 expect ( actual . map ( ( w ) => w . index ) ) . toEqual ( [ 0 , 1 ] ) ;
278301 } ) ;
279302
280- it ( "for an index-less waitpoint sitting beside indexed ones" , async ( ) => {
303+ postgresTest ( "for an index-less waitpoint sitting beside indexed ones" , async ( { prisma } ) => {
304+ // Seeded to match the RUN row's own output, which is the parity premise: TaskRun.output
305+ // holds the same string the waitpoint carried.
306+ const childRunId = await seedChildRunWithOutput ( prisma , '{"ok":true}' ) ;
281307 const { expected, actual } = await bothPaths (
308+ prisma ,
282309 [
283310 pair ( { id : "wp_indexless" , type : "MANUAL" , output : '{"token":1}' } ) ,
284311 pair ( {
285312 id : "wp_run" ,
286313 type : "RUN" ,
287314 output : '{"ok":true}' ,
288- completedByTaskRunId : CHILD_RUN_ID ,
315+ completedByTaskRunId : childRunId ,
289316 } ) ,
290317 ] ,
291318 [ "wp_run" ] ,
@@ -300,8 +327,9 @@ describe("the resolver reproduces the existing hydration", () => {
300327 // an output, but the executor never reads it (sharedRuntimeManager.resolveWaitpoint
301328 // early-returns on type). Pinned so that if that early return ever goes away, this fails and
302329 // says why, instead of the output silently being missing at resume.
303- it ( "deliberately drops a BATCH output, unlike the oracle" , async ( ) => {
330+ postgresTest ( "deliberately drops a BATCH output, unlike the oracle" , async ( { prisma } ) => {
304331 const { expected, actual } = await bothPaths (
332+ prisma ,
305333 [
306334 pair ( {
307335 id : "wp_batch" ,
@@ -319,14 +347,16 @@ describe("the resolver reproduces the existing hydration", () => {
319347 expect ( actual [ 0 ] ?. outputIsError ) . toBe ( true ) ;
320348 } ) ;
321349
322- it ( "for every type at once, under a batch" , async ( ) => {
350+ postgresTest ( "for every type at once, under a batch" , async ( { prisma } ) => {
351+ const childRunId = await seedChildRunWithOutput ( prisma , '{"ok":true}' ) ;
323352 const { expected, actual } = await bothPaths (
353+ prisma ,
324354 [
325355 pair ( {
326356 id : "wp_run" ,
327357 type : "RUN" ,
328358 output : '{"ok":true}' ,
329- completedByTaskRunId : CHILD_RUN_ID ,
359+ completedByTaskRunId : childRunId ,
330360 } ) ,
331361 pair ( { id : "wp_batch" , type : "BATCH" , completedByBatchId : BATCH_ID } ) ,
332362 pair ( {
0 commit comments