@@ -55,7 +55,10 @@ export const GET = withRouteHandler(async (request: NextRequest) => {
5555 const staleDurationMinutes = Math . round ( staleDurationMs / 60000 )
5656 const totalDurationMs = Math . min ( staleDurationMs , MAX_INT32 )
5757
58- await db
58+ // Conditional on status='running' so a worker that completes between the
59+ // select and this update keeps its own terminal status (and its own
60+ // ExecutionCompleted point) — no force-fail overwrite, no double count.
61+ const transitioned = await db
5962 . update ( workflowExecutionLogs )
6063 . set ( {
6164 status : 'failed' ,
@@ -67,7 +70,20 @@ export const GET = withRouteHandler(async (request: NextRequest) => {
6770 to_jsonb(${ `Execution terminated: worker timeout or crash after ${ staleDurationMinutes } minutes` } ::text)
6871 )` ,
6972 } )
70- . where ( eq ( workflowExecutionLogs . id , execution . id ) )
73+ . where (
74+ and (
75+ eq ( workflowExecutionLogs . id , execution . id ) ,
76+ eq ( workflowExecutionLogs . status , 'running' )
77+ )
78+ )
79+ . returning ( { id : workflowExecutionLogs . id } )
80+
81+ if ( transitioned . length === 0 ) {
82+ logger . info ( `Skipped stale execution ${ execution . executionId } : no longer running` , {
83+ workflowId : execution . workflowId ,
84+ } )
85+ continue
86+ }
7187
7288 logger . info ( `Cleaned up stale execution ${ execution . executionId } ` , {
7389 workflowId : execution . workflowId ,
0 commit comments