@@ -51,6 +51,15 @@ export function wrapRequestHandler(
5151
5252 const waitUntil = context ?. waitUntil ?. bind ?.( context ) ;
5353
54+ // Track whether flush has been scheduled to prevent duplicate calls
55+ let flushScheduled = false ;
56+ const scheduleFlush = ( timeout : number = 2000 ) : void => {
57+ if ( ! flushScheduled && waitUntil ) {
58+ flushScheduled = true ;
59+ waitUntil ( flush ( timeout ) ) ;
60+ }
61+ } ;
62+
5463 const client = init ( { ...options , ctx : context } ) ;
5564 isolationScope . setClient ( client ) ;
5665
@@ -89,7 +98,7 @@ export function wrapRequestHandler(
8998 }
9099 throw e ;
91100 } finally {
92- waitUntil ?. ( flush ( 2000 ) ) ;
101+ scheduleFlush ( ) ;
93102 }
94103 }
95104
@@ -112,7 +121,7 @@ export function wrapRequestHandler(
112121 if ( captureErrors ) {
113122 captureException ( e , { mechanism : { handled : false , type : 'auto.http.cloudflare' } } ) ;
114123 }
115- waitUntil ?. ( flush ( 2000 ) ) ;
124+ scheduleFlush ( ) ;
116125 throw e ;
117126 }
118127
@@ -146,7 +155,10 @@ export function wrapRequestHandler(
146155 } ) ( ) ;
147156
148157 // Use waitUntil to keep context alive and flush after span ends
149- waitUntil ?.( streamMonitor . then ( ( ) => flush ( 2000 ) ) ) ;
158+ if ( waitUntil ) {
159+ flushScheduled = true ;
160+ waitUntil ( streamMonitor . then ( ( ) => flush ( 2000 ) ) ) ;
161+ }
150162
151163 // Return response with client stream
152164 return new Response ( clientStream , {
@@ -158,7 +170,7 @@ export function wrapRequestHandler(
158170
159171 // Non-streaming response - end span immediately and return original
160172 span . end ( ) ;
161- waitUntil ?. ( flush ( 2000 ) ) ;
173+ scheduleFlush ( ) ;
162174 return classification . response ;
163175 } ) ;
164176 } ,
0 commit comments