@@ -72,7 +72,7 @@ import {
7272 translateHTTPError ,
7373} from './errors' ;
7474import { QueueFlushingPlugin } from './plugins/QueueFlushingPlugin' ;
75- import { WaitingPlugin } from './plugins/Waiting ' ;
75+ import { WaitingPlugin } from './plugin ' ;
7676
7777type OnPluginAddedCallback = ( plugin : Plugin ) => void ;
7878
@@ -98,11 +98,6 @@ export class SegmentClient {
9898 private isAddingPlugins = false ;
9999
100100 private timeline : Timeline ;
101- // running state (matches Kotlin's running flag)
102- private isRunning = true ;
103-
104- // Waiting plugin instance (buffers events while paused)
105- private waitingPlugin ?: WaitingPlugin ;
106101
107102 private pluginsToAdd : Plugin [ ] = [ ] ;
108103
@@ -206,17 +201,17 @@ export class SegmentClient {
206201 this . store = store ;
207202 this . timeline = new Timeline ( ) ;
208203
209- // create and add waiting plugin immediately so early events get buffered.
210- try {
211- this . waitingPlugin = new WaitingPlugin ( ) ;
212- // add directly to timeline via addPlugin to ensure configure() is called immediately
213- this . addPlugin ( this . waitingPlugin ) ;
214- // initial running state false until init completes (mirrors Kotlin semantics)
215- this . isRunning = false ;
216- } catch ( e ) {
217- // if WaitingPlugin instantiation or add fails, fallback to running=true
218- this . isRunning = true ;
219- }
204+ // // create and add waiting plugin immediately so early events get buffered.
205+ // try {
206+ // this.waitingPlugin = new WaitingPlugin();
207+ // // add directly to timeline via addPlugin to ensure configure() is called immediately
208+ // this.addPlugin(this.waitingPlugin);
209+ // // initial running state false until init completes (mirrors Kotlin semantics)
210+ // this.isRunning = false;
211+ // } catch (e) {
212+ // // if WaitingPlugin instantiation or add fails, fallback to running=true
213+ // this.isRunning = true;
214+ // }
220215
221216 // Initialize the watchables
222217 this . context = {
@@ -313,10 +308,6 @@ export class SegmentClient {
313308 if ( ( await this . store . isReady . get ( true ) ) === false ) {
314309 await this . storageReady ( ) ;
315310 }
316-
317- // Pause pipeline at init start (buffer events until init completes)
318- this . pauseEventProcessing ( ) ;
319-
320311 // Get new settings from segment
321312 // It's important to run this before checkInstalledVersion and trackDeeplinks to give time for destination plugins
322313 // which make use of the settings object to initialize
@@ -330,8 +321,6 @@ export class SegmentClient {
330321 ] ) ;
331322 await this . onReady ( ) ;
332323 this . isReady . value = true ;
333- // Resume pipeline before processing pending events so WaitingPlugin flushes
334- await this . resumeEventProcessing ( ) ;
335324 // Process all pending events
336325 await this . processPendingEvents ( ) ;
337326 // Trigger manual flush
@@ -487,17 +476,24 @@ export class SegmentClient {
487476 settings
488477 ) ;
489478 }
490-
491- if ( ! this . isReady . value ) {
479+ console . log ( '!this.isReady.value' , ! this . isReady . value ) ;
480+ if ( ! this . isReady . value && ! ( plugin instanceof WaitingPlugin ) ) {
492481 this . pluginsToAdd . push ( plugin ) ;
493482 } else {
483+ console . log ( 'this.addPlugin' ) ;
494484 this . addPlugin ( plugin ) ;
495485 }
496486 }
497487
498488 private addPlugin ( plugin : Plugin ) {
499489 plugin . configure ( this ) ;
500490 this . timeline . add ( plugin ) ;
491+ //check for waiting plugin here
492+ if ( plugin instanceof WaitingPlugin ) {
493+ console . log ( 'add plugin' ) ;
494+ this . pauseEventProcessingForPlugin ( plugin ) ;
495+ }
496+
501497 this . triggerOnPluginLoaded ( plugin ) ;
502498 }
503499
@@ -534,7 +530,7 @@ export class SegmentClient {
534530 ) : Promise < SegmentEvent | undefined > {
535531 const event = await this . applyContextData ( incomingEvent ) ;
536532 this . flushPolicyExecuter . notify ( event ) ;
537- return this . timeline . process ( event ) ;
533+ return await this . timeline . process ( event ) ;
538534 }
539535
540536 private async trackDeepLinks ( ) {
@@ -1049,45 +1045,58 @@ export class SegmentClient {
10491045
10501046 return totalEventsCount ;
10511047 }
1052- /*
1053- * Running / pause/resume helpers (Kotlin parity)
1054- */
1048+ private resumeTimeoutId ?: ReturnType < typeof setTimeout > ;
1049+ private waitingPlugins = new Set < WaitingPlugin > ( ) ;
10551050
1056- public running ( ) {
1057- return this . isRunning ;
1058- }
10591051 /**
10601052 * Pause event processing globally. Events will be buffered into pendingEvents and WaitingPlugin.
10611053 * An auto-resume will be scheduled after `timeout` ms.
10621054 */
1063- public pauseEventProcessing ( timeout = 30000 ) {
1064- if ( ! this . isRunning ) {
1055+ pauseEventProcessingForPlugin ( plugin ?: WaitingPlugin ) {
1056+ if ( plugin ) {
1057+ this . waitingPlugins . add ( plugin ) ;
1058+ }
1059+ this . pauseEventProcessing ( ) ;
1060+ }
1061+ async resumeEventProcessingForPlugin ( plugin ?: WaitingPlugin ) {
1062+ if ( plugin ) {
1063+ this . waitingPlugins . delete ( plugin ) ;
1064+ }
1065+ if ( this . waitingPlugins . size > 0 ) {
1066+ return ; // still blocked
1067+ }
1068+
1069+ await this . resumeEventProcessing ( ) ;
1070+ }
1071+
1072+ pauseEventProcessing ( timeout = 30000 ) {
1073+ // IMPORTANT: ignore repeated pauses
1074+ if ( ! this . isReady . value ) {
10651075 return ;
10661076 }
10671077
1068- this . isRunning = false ;
1069- try {
1070- this . waitingPlugin ?. pause ( ) ;
1071- } catch {
1072- // ignore if plugin not present
1078+ this . isReady . value = false ;
1079+
1080+ // clear previous timeout if any
1081+ if ( this . resumeTimeoutId ) {
1082+ clearTimeout ( this . resumeTimeoutId ) ;
10731083 }
10741084
1075- // auto-resume after timeout to avoid permanent blocking
1076- setTimeout ( ( ) => {
1077- void this . resumeEventProcessing ( ) ;
1085+ this . resumeTimeoutId = setTimeout ( async ( ) => {
1086+ await this . resumeEventProcessing ( ) ;
10781087 } , timeout ) ;
10791088 }
1080- public async resumeEventProcessing ( ) {
1081- if ( this . isRunning ) {
1089+ async resumeEventProcessing ( ) {
1090+ if ( this . isReady . value ) {
10821091 return ;
10831092 }
10841093
1085- this . isRunning = true ;
1086-
1087- try {
1088- await this . waitingPlugin ?. resume ( ) ;
1089- } catch {
1090- // ignore plugin errors during resume
1094+ if ( this . resumeTimeoutId ) {
1095+ clearTimeout ( this . resumeTimeoutId ) ;
1096+ this . resumeTimeoutId = undefined ;
10911097 }
1098+ // this.waitingPlugins.clear();
1099+ this . isReady . value = true ;
1100+ await this . processPendingEvents ( ) ;
10921101 }
10931102}
0 commit comments