@@ -16,6 +16,9 @@ export class CloudflareClient extends ServerRuntimeClient {
1616 private _spanCompletionPromise : Promise < void > | null = null ;
1717 private _resolveSpanCompletion : ( ( ) => void ) | null = null ;
1818
19+ private _unsubscribeSpanStart : ( ( ) => void ) | null = null ;
20+ private _unsubscribeSpanEnd : ( ( ) => void ) | null = null ;
21+
1922 /**
2023 * Creates a new Cloudflare SDK instance.
2124 * @param options Configuration options for this SDK.
@@ -37,7 +40,7 @@ export class CloudflareClient extends ServerRuntimeClient {
3740 this . _flushLock = flushLock ;
3841
3942 // Track span lifecycle to know when to flush
40- this . on ( 'spanStart' , span => {
43+ this . _unsubscribeSpanStart = this . on ( 'spanStart' , span => {
4144 const spanId = span . spanContext ( ) . spanId ;
4245 DEBUG_BUILD && debug . log ( '[CloudflareClient] Span started:' , spanId ) ;
4346 this . _pendingSpans . add ( spanId ) ;
@@ -49,7 +52,7 @@ export class CloudflareClient extends ServerRuntimeClient {
4952 }
5053 } ) ;
5154
52- this . on ( 'spanEnd' , span => {
55+ this . _unsubscribeSpanEnd = this . on ( 'spanEnd' , span => {
5356 const spanId = span . spanContext ( ) . spanId ;
5457 DEBUG_BUILD && debug . log ( '[CloudflareClient] Span ended:' , spanId ) ;
5558 this . _pendingSpans . delete ( spanId ) ;
@@ -99,6 +102,38 @@ export class CloudflareClient extends ServerRuntimeClient {
99102 return super . flush ( timeout ) ;
100103 }
101104
105+ /**
106+ * Disposes of the client and releases all resources.
107+ *
108+ * This method clears all Cloudflare-specific state in addition to the base client cleanup.
109+ * It unsubscribes from span lifecycle events and clears pending span tracking.
110+ *
111+ * Call this method after flushing to allow the client to be garbage collected.
112+ * After calling dispose(), the client should not be used anymore.
113+ */
114+ public override dispose ( ) : void {
115+ DEBUG_BUILD && debug . log ( '[CloudflareClient] Disposing client...' ) ;
116+
117+ // Unsubscribe from span lifecycle events to break circular references
118+ if ( this . _unsubscribeSpanStart ) {
119+ this . _unsubscribeSpanStart ( ) ;
120+ this . _unsubscribeSpanStart = null ;
121+ }
122+ if ( this . _unsubscribeSpanEnd ) {
123+ this . _unsubscribeSpanEnd ( ) ;
124+ this . _unsubscribeSpanEnd = null ;
125+ }
126+
127+ // Clear pending spans and completion promise
128+ this . _resetSpanCompletionPromise ( ) ;
129+
130+ // Clear flushLock reference to break context retention
131+ ( this as unknown as { _flushLock : ReturnType < typeof makeFlushLock > | void } ) . _flushLock = undefined ;
132+
133+ // Call base class dispose to clean up common state
134+ super . dispose ( ) ;
135+ }
136+
102137 /**
103138 * Resets the span completion promise and resolve function.
104139 */
0 commit comments