@@ -18,6 +18,7 @@ const {
1818 mockGetCustomBlockAuthority,
1919 mockGetUserEmailById,
2020 mockAdmitCustomBlockChildExecution,
21+ mockTrackChildFinalization,
2122 mockBuildTraceSpans,
2223 mockSafeStart,
2324 mockSafeComplete,
@@ -33,6 +34,7 @@ const {
3334 mockGetCustomBlockAuthority : vi . fn ( ) ,
3435 mockGetUserEmailById : vi . fn ( ) ,
3536 mockAdmitCustomBlockChildExecution : vi . fn ( ) ,
37+ mockTrackChildFinalization : vi . fn ( ) ,
3638 mockBuildTraceSpans : vi . fn ( ) ,
3739 mockSafeStart : vi . fn ( ) ,
3840 mockSafeComplete : vi . fn ( ) ,
@@ -63,6 +65,7 @@ vi.mock('@/lib/logs/execution/trace-spans/trace-spans', () => ({
6365
6466vi . mock ( '@/lib/workflows/custom-blocks/child-execution' , ( ) => ( {
6567 admitCustomBlockChildExecution : mockAdmitCustomBlockChildExecution ,
68+ trackChildFinalization : mockTrackChildFinalization ,
6669 buildCustomBlockCorrelation : ( params : Record < string , any > ) =>
6770 params . invokerExecutionId
6871 ? { source : 'custom_block' , executionId : params . invokerExecutionId }
@@ -1247,6 +1250,24 @@ describe('WorkflowBlockHandler', () => {
12471250 expect ( error . cause ) . toBeUndefined ( )
12481251 } )
12491252
1253+ it ( 'registers the finalization so a cancelled parent can still drain it' , async ( ) => {
1254+ await handler . execute ( customBlockContext ( ) , customBlock ( ) , { } )
1255+
1256+ expect ( mockTrackChildFinalization ) . toHaveBeenCalledTimes ( 1 )
1257+ const [ invokerId , promise ] = mockTrackChildFinalization . mock . calls [ 0 ]
1258+ expect ( invokerId ) . toBe ( 'parent-execution-id' )
1259+ expect ( promise ) . toBeInstanceOf ( Promise )
1260+ } )
1261+
1262+ it ( 'registers the finalization on the failure path too' , async ( ) => {
1263+ mockExecutorExecute . mockRejectedValue ( new Error ( 'boom' ) )
1264+
1265+ await handler . execute ( customBlockContext ( ) , customBlock ( ) , { } ) . catch ( ( ) => { } )
1266+
1267+ expect ( mockTrackChildFinalization ) . toHaveBeenCalledTimes ( 1 )
1268+ expect ( mockTrackChildFinalization . mock . calls [ 0 ] [ 0 ] ) . toBe ( 'parent-execution-id' )
1269+ } )
1270+
12501271 it ( 'never leaks the source workflow name when the child returns success: false' , async ( ) => {
12511272 mockExecutorExecute . mockResolvedValue ( {
12521273 success : false ,
0 commit comments