@@ -5,7 +5,11 @@ import { validate as uuidValidate, v4 as uuidv4 } from 'uuid'
55import { z } from 'zod'
66import { checkHybridAuth } from '@/lib/auth/hybrid'
77import { isTriggerDevEnabled } from '@/lib/core/config/feature-flags'
8- import { getTimeoutErrorMessage , isTimeoutError } from '@/lib/core/execution-limits'
8+ import {
9+ createTimeoutAbortController ,
10+ getTimeoutErrorMessage ,
11+ isTimeoutError ,
12+ } from '@/lib/core/execution-limits'
913import { generateRequestId } from '@/lib/core/utils/request'
1014import { SSE_HEADERS } from '@/lib/core/utils/sse'
1115import { getBaseUrl } from '@/lib/core/utils/urls'
@@ -402,17 +406,9 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
402406
403407 if ( ! enableSSE ) {
404408 logger . info ( `[${ requestId } ] Using non-SSE execution (direct JSON response)` )
405- const syncTimeout = preprocessResult . executionTimeout ?. sync
406- const abortController = new AbortController ( )
407- let isTimedOut = false
408- let timeoutId : NodeJS . Timeout | undefined
409-
410- if ( syncTimeout ) {
411- timeoutId = setTimeout ( ( ) => {
412- isTimedOut = true
413- abortController . abort ( )
414- } , syncTimeout )
415- }
409+ const timeoutController = createTimeoutAbortController (
410+ preprocessResult . executionTimeout ?. sync
411+ )
416412
417413 try {
418414 const metadata : ExecutionMetadata = {
@@ -447,12 +443,18 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
447443 includeFileBase64,
448444 base64MaxBytes,
449445 stopAfterBlockId,
450- abortSignal : abortController . signal ,
446+ abortSignal : timeoutController . signal ,
451447 } )
452448
453- if ( result . status === 'cancelled' && isTimedOut && syncTimeout ) {
454- const timeoutErrorMessage = getTimeoutErrorMessage ( null , syncTimeout )
455- logger . info ( `[${ requestId } ] Non-SSE execution timed out` , { timeoutMs : syncTimeout } )
449+ if (
450+ result . status === 'cancelled' &&
451+ timeoutController . isTimedOut ( ) &&
452+ timeoutController . timeoutMs
453+ ) {
454+ const timeoutErrorMessage = getTimeoutErrorMessage ( null , timeoutController . timeoutMs )
455+ logger . info ( `[${ requestId } ] Non-SSE execution timed out` , {
456+ timeoutMs : timeoutController . timeoutMs ,
457+ } )
456458 await loggingSession . markAsFailed ( timeoutErrorMessage )
457459
458460 await cleanupExecutionBase64Cache ( executionId )
@@ -535,7 +537,7 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
535537 { status : 500 }
536538 )
537539 } finally {
538- if ( timeoutId ) clearTimeout ( timeoutId )
540+ timeoutController . cleanup ( )
539541 }
540542 }
541543
@@ -578,18 +580,8 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
578580 }
579581
580582 const encoder = new TextEncoder ( )
581- const abortController = new AbortController ( )
583+ const timeoutController = createTimeoutAbortController ( preprocessResult . executionTimeout ?. sync )
582584 let isStreamClosed = false
583- let isTimedOut = false
584-
585- const syncTimeout = preprocessResult . executionTimeout ?. sync
586- let timeoutId : NodeJS . Timeout | undefined
587- if ( syncTimeout ) {
588- timeoutId = setTimeout ( ( ) => {
589- isTimedOut = true
590- abortController . abort ( )
591- } , syncTimeout )
592- }
593585
594586 const stream = new ReadableStream < Uint8Array > ( {
595587 async start ( controller ) {
@@ -780,7 +772,7 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
780772 onStream,
781773 } ,
782774 loggingSession,
783- abortSignal : abortController . signal ,
775+ abortSignal : timeoutController . signal ,
784776 includeFileBase64,
785777 base64MaxBytes,
786778 stopAfterBlockId,
@@ -816,9 +808,11 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
816808 }
817809
818810 if ( result . status === 'cancelled' ) {
819- if ( isTimedOut && syncTimeout ) {
820- const timeoutErrorMessage = getTimeoutErrorMessage ( null , syncTimeout )
821- logger . info ( `[${ requestId } ] Workflow execution timed out` , { timeoutMs : syncTimeout } )
811+ if ( timeoutController . isTimedOut ( ) && timeoutController . timeoutMs ) {
812+ const timeoutErrorMessage = getTimeoutErrorMessage ( null , timeoutController . timeoutMs )
813+ logger . info ( `[${ requestId } ] Workflow execution timed out` , {
814+ timeoutMs : timeoutController . timeoutMs ,
815+ } )
822816
823817 await loggingSession . markAsFailed ( timeoutErrorMessage )
824818
@@ -871,9 +865,9 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
871865 // Cleanup base64 cache for this execution
872866 await cleanupExecutionBase64Cache ( executionId )
873867 } catch ( error : unknown ) {
874- const isTimeout = isTimeoutError ( error ) || isTimedOut
868+ const isTimeout = isTimeoutError ( error ) || timeoutController . isTimedOut ( )
875869 const errorMessage = isTimeout
876- ? getTimeoutErrorMessage ( error , syncTimeout )
870+ ? getTimeoutErrorMessage ( error , timeoutController . timeoutMs )
877871 : error instanceof Error
878872 ? error . message
879873 : 'Unknown error'
@@ -899,7 +893,7 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
899893 } ,
900894 } )
901895 } finally {
902- if ( timeoutId ) clearTimeout ( timeoutId )
896+ timeoutController . cleanup ( )
903897 if ( ! isStreamClosed ) {
904898 try {
905899 controller . enqueue ( encoder . encode ( 'data: [DONE]\n\n' ) )
@@ -910,9 +904,9 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
910904 } ,
911905 cancel ( ) {
912906 isStreamClosed = true
913- if ( timeoutId ) clearTimeout ( timeoutId )
907+ timeoutController . cleanup ( )
914908 logger . info ( `[${ requestId } ] Client aborted SSE stream, signalling cancellation` )
915- abortController . abort ( )
909+ timeoutController . abort ( )
916910 markExecutionCancelled ( executionId ) . catch ( ( ) => { } )
917911 } ,
918912 } )
0 commit comments