@@ -594,3 +594,115 @@ describe("createRun / createFailedRun write the run and its associated waitpoint
594594 }
595595 ) ;
596596} ) ;
597+
598+ // The dedicated (#new) leg connects completed waitpoints through the `CompletedWaitpoint` join table
599+ // (createMany), where the legacy leg uses the implicit `_completedWaitpoints` M2M. Both must commit the
600+ // snapshot and its links together: a snapshot that commits before its links can be read waitpoint-less
601+ // from a lagging replica, and the runner's EXECUTING branch no-ops on an empty set -> the resume hangs.
602+ describe ( "createExecutionSnapshot / lockRunToWorker write the snapshot and its links atomically (dedicated)" , ( ) => {
603+ heteroRunOpsPostgresTest (
604+ "createExecutionSnapshot rolls the snapshot back if the CompletedWaitpoint insert fails" ,
605+ async ( { prisma17 } ) => {
606+ const newStore = makeDedicatedStore ( prisma17 ) ;
607+ const env = await seedEnvironment ( prisma17 , "dedicated" , "ces_ded" ) ;
608+ const runId = `run_${ NEW_ID_26 } ` ;
609+ await newStore . createRun (
610+ buildCreateRunInput ( {
611+ runId,
612+ friendlyId : "run_ces_ded" ,
613+ organizationId : env . organization . id ,
614+ projectId : env . project . id ,
615+ runtimeEnvironmentId : env . environment . id ,
616+ } )
617+ ) ;
618+
619+ // Force the dedicated join insert (completedWaitpoint.createMany) to fail mid-write.
620+ await prisma17 . $executeRawUnsafe ( 'DROP TABLE "CompletedWaitpoint"' ) ;
621+
622+ await expect (
623+ // Base client as `tx` = how the engine threads its base prisma through
624+ // (continueRunIfUnblocked -> executionSnapshotSystem.createExecutionSnapshot(prisma, ...)).
625+ // It is NOT an interactive transaction, so the store must still open its own to stay atomic.
626+ newStore . createExecutionSnapshot (
627+ {
628+ run : { id : runId , status : "EXECUTING" , attemptNumber : 1 } ,
629+ snapshot : {
630+ executionStatus : "EXECUTING_WITH_WAITPOINTS" ,
631+ description : "Run was blocked by a waitpoint." ,
632+ } ,
633+ environmentId : env . environment . id ,
634+ environmentType : "DEVELOPMENT" ,
635+ projectId : env . project . id ,
636+ organizationId : env . project . id ,
637+ completedWaitpoints : [ { id : `wp_${ NEW_ID_26 } ` , index : 0 } ] ,
638+ } ,
639+ prisma17 as never
640+ )
641+ ) . rejects . toThrow ( ) ;
642+
643+ const snap = await prisma17 . taskRunExecutionSnapshot . findFirst ( {
644+ where : { runId, executionStatus : "EXECUTING_WITH_WAITPOINTS" } ,
645+ } ) ;
646+ expect ( snap ) . toBeNull ( ) ;
647+ }
648+ ) ;
649+
650+ heteroRunOpsPostgresTest (
651+ "lockRunToWorker rolls the snapshot and run lock back if the CompletedWaitpoint insert fails" ,
652+ async ( { prisma17 } ) => {
653+ const newStore = makeDedicatedStore ( prisma17 ) ;
654+ const env = await seedEnvironment ( prisma17 , "dedicated" , "lock_ded" ) ;
655+ const runId = `run_${ NEW_ID_26 } ` ;
656+ await newStore . createRun (
657+ buildCreateRunInput ( {
658+ runId,
659+ friendlyId : "run_lock_ded" ,
660+ organizationId : env . organization . id ,
661+ projectId : env . project . id ,
662+ runtimeEnvironmentId : env . environment . id ,
663+ } )
664+ ) ;
665+ const prior = await prisma17 . taskRunExecutionSnapshot . findFirstOrThrow ( { where : { runId } } ) ;
666+
667+ await prisma17 . $executeRawUnsafe ( 'DROP TABLE "CompletedWaitpoint"' ) ;
668+
669+ const snapshotId = `snap_${ NEW_ID_26 } ` ;
670+ await expect (
671+ // lockedById/lockedToVersionId/lockedQueueId are FK-free scalars on the dedicated subset, so
672+ // synthetic ids are fine; the base client as `tx` mirrors the dequeue path (no interactive tx).
673+ newStore . lockRunToWorker (
674+ runId ,
675+ {
676+ lockedAt : new Date ( ) ,
677+ lockedById : `bwt_${ NEW_ID_26 } ` ,
678+ lockedToVersionId : `bw_${ NEW_ID_26 } ` ,
679+ lockedQueueId : `queue_${ NEW_ID_26 } ` ,
680+ startedAt : new Date ( ) ,
681+ baseCostInCents : 5 ,
682+ machinePreset : "small-1x" ,
683+ taskVersion : "20260601.1" ,
684+ sdkVersion : "3.0.0" ,
685+ cliVersion : "3.0.0" ,
686+ maxDurationInSeconds : null ,
687+ snapshot : {
688+ id : snapshotId ,
689+ previousSnapshotId : prior . id ,
690+ environmentId : env . environment . id ,
691+ environmentType : "DEVELOPMENT" ,
692+ projectId : env . project . id ,
693+ organizationId : env . project . id ,
694+ completedWaitpointIds : [ `wp_${ NEW_ID_26 } ` ] ,
695+ completedWaitpointOrder : [ `wp_${ NEW_ID_26 } ` ] ,
696+ } ,
697+ } ,
698+ prisma17 as never
699+ )
700+ ) . rejects . toThrow ( ) ;
701+
702+ const snap = await prisma17 . taskRunExecutionSnapshot . findUnique ( { where : { id : snapshotId } } ) ;
703+ expect ( snap ) . toBeNull ( ) ;
704+ const run = await prisma17 . taskRun . findUniqueOrThrow ( { where : { id : runId } } ) ;
705+ expect ( run . status ) . not . toBe ( "DEQUEUED" ) ;
706+ }
707+ ) ;
708+ } ) ;
0 commit comments