@@ -503,6 +503,104 @@ describe('initialization options', () => {
503
503
expect ( callCount ) . toBe ( 2 ) ;
504
504
} ) ;
505
505
506
+ it ( 'only fetches/does initialization workload once if init is called multiple times concurrently' , async ( ) => {
507
+ let callCount = 0 ;
508
+
509
+ global . fetch = jest . fn ( ( ) => {
510
+ ++ callCount ;
511
+ return Promise . resolve ( {
512
+ ok : true ,
513
+ status : 200 ,
514
+ json : ( ) => Promise . resolve ( mockConfigResponse ) ,
515
+ } ) ;
516
+ } ) as jest . Mock ;
517
+
518
+ const inits : Promise < EppoClient > [ ] = [ ] ;
519
+ [ ...Array ( 10 ) . keys ( ) ] . forEach ( ( ) => {
520
+ inits . push (
521
+ init ( {
522
+ apiKey,
523
+ baseUrl,
524
+ assignmentLogger : mockLogger ,
525
+ } ) ,
526
+ ) ;
527
+ } ) ;
528
+
529
+ // Advance timers mid-init to allow retrying
530
+ await jest . advanceTimersByTimeAsync ( maxRetryDelay ) ;
531
+
532
+ // Await for all the initialization calls to resolve
533
+ const client = await Promise . race ( inits ) ;
534
+ await Promise . all ( inits ) ;
535
+
536
+ expect ( callCount ) . toBe ( 1 ) ;
537
+ expect ( client . getStringAssignment ( flagKey , 'subject' , { } , 'default-value' ) ) . toBe ( 'control' ) ;
538
+ } ) ;
539
+
540
+ it ( 'only fetches/does initialization workload once per API key if init is called multiple times concurrently' , async ( ) => {
541
+ let callCount = 0 ;
542
+
543
+ global . fetch = jest . fn ( ( ) => {
544
+ ++ callCount ;
545
+ return Promise . resolve ( {
546
+ ok : true ,
547
+ status : 200 ,
548
+ json : ( ) => Promise . resolve ( mockConfigResponse ) ,
549
+ } ) ;
550
+ } ) as jest . Mock ;
551
+
552
+ const inits : Promise < EppoClient > [ ] = [ ] ;
553
+ [
554
+ 'KEY_1' ,
555
+ 'KEY_2' ,
556
+ 'KEY_1' ,
557
+ 'KEY_2' ,
558
+ 'KEY_1' ,
559
+ 'KEY_2' ,
560
+ 'KEY_3' ,
561
+ 'KEY_1' ,
562
+ 'KEY_2' ,
563
+ 'KEY_3' ,
564
+ ] . forEach ( ( varyingAPIKey ) => {
565
+ inits . push (
566
+ init ( {
567
+ apiKey : varyingAPIKey ,
568
+ baseUrl,
569
+ forceReinitialize : true ,
570
+ assignmentLogger : mockLogger ,
571
+ } ) ,
572
+ ) ;
573
+ } ) ;
574
+
575
+ // Advance timers mid-init to allow retrying
576
+ await jest . advanceTimersByTimeAsync ( maxRetryDelay ) ;
577
+
578
+ // Await for all the initialization calls to resolve
579
+ const client = await Promise . race ( inits ) ;
580
+ await Promise . all ( inits ) ;
581
+
582
+ expect ( callCount ) . toBe ( 3 ) ;
583
+ callCount = 0 ;
584
+ expect ( client . getStringAssignment ( flagKey , 'subject' , { } , 'default-value' ) ) . toBe ( 'control' ) ;
585
+
586
+ const reInits : Promise < EppoClient > [ ] = [ ] ;
587
+ [ 'KEY_1' , 'KEY_2' , 'KEY_3' , 'KEY_4' ] . forEach ( ( varyingAPIKey ) => {
588
+ reInits . push (
589
+ init ( {
590
+ apiKey : varyingAPIKey ,
591
+ forceReinitialize : true ,
592
+ baseUrl,
593
+ assignmentLogger : mockLogger ,
594
+ } ) ,
595
+ ) ;
596
+ } ) ;
597
+
598
+ await Promise . all ( reInits ) ;
599
+
600
+ expect ( callCount ) . toBe ( 4 ) ;
601
+ expect ( client . getStringAssignment ( flagKey , 'subject' , { } , 'default-value' ) ) . toBe ( 'control' ) ;
602
+ } ) ;
603
+
506
604
it ( 'do not reinitialize if already initialized' , async ( ) => {
507
605
let callCount = 0 ;
508
606
0 commit comments