@@ -41,7 +41,11 @@ function updateStateCallBackForExpectedStateSequence(
41
41
) {
42
42
const actualStateSequence : ConnectivityState [ ] = [ ] ;
43
43
let lastPicker : Picker | null = null ;
44
+ let finished = false ;
44
45
return ( connectivityState : ConnectivityState , picker : Picker ) => {
46
+ if ( finished ) {
47
+ return ;
48
+ }
45
49
// Ignore duplicate state transitions
46
50
if (
47
51
connectivityState === actualStateSequence [ actualStateSequence . length - 1 ]
@@ -60,6 +64,7 @@ function updateStateCallBackForExpectedStateSequence(
60
64
if (
61
65
expectedStateSequence [ actualStateSequence . length ] !== connectivityState
62
66
) {
67
+ finished = true ;
63
68
done (
64
69
new Error (
65
70
`Unexpected state ${
@@ -69,10 +74,12 @@ function updateStateCallBackForExpectedStateSequence(
69
74
) } ]`
70
75
)
71
76
) ;
77
+ return ;
72
78
}
73
79
actualStateSequence . push ( connectivityState ) ;
74
80
lastPicker = picker ;
75
81
if ( actualStateSequence . length === expectedStateSequence . length ) {
82
+ finished = true ;
76
83
done ( ) ;
77
84
}
78
85
} ;
@@ -90,7 +97,7 @@ describe('Shuffler', () => {
90
97
} ) ;
91
98
} ) ;
92
99
93
- describe ( 'pick_first load balancing policy' , ( ) => {
100
+ describe . only ( 'pick_first load balancing policy' , ( ) => {
94
101
const config = new PickFirstLoadBalancingConfig ( false ) ;
95
102
let subchannels : MockSubchannel [ ] = [ ] ;
96
103
const baseChannelControlHelper : ChannelControlHelper = {
@@ -462,6 +469,87 @@ describe('pick_first load balancing policy', () => {
462
469
} ) ;
463
470
} ) ;
464
471
} ) ;
472
+ it ( 'Should request reresolution every time each child reports TF' , done => {
473
+ let reresolutionRequestCount = 0 ;
474
+ const targetReresolutionRequestCount = 3 ;
475
+ const currentStartState = ConnectivityState . IDLE ;
476
+ const channelControlHelper = createChildChannelControlHelper (
477
+ baseChannelControlHelper ,
478
+ {
479
+ createSubchannel : ( subchannelAddress , subchannelArgs ) => {
480
+ const subchannel = new MockSubchannel (
481
+ subchannelAddressToString ( subchannelAddress ) ,
482
+ currentStartState
483
+ ) ;
484
+ subchannels . push ( subchannel ) ;
485
+ return subchannel ;
486
+ } ,
487
+ updateState : updateStateCallBackForExpectedStateSequence (
488
+ [ ConnectivityState . CONNECTING , ConnectivityState . TRANSIENT_FAILURE ] ,
489
+ err => setImmediate ( ( ) => {
490
+ assert . strictEqual ( reresolutionRequestCount , targetReresolutionRequestCount ) ;
491
+ done ( err ) ;
492
+ } )
493
+ ) ,
494
+ requestReresolution : ( ) => {
495
+ reresolutionRequestCount += 1 ;
496
+ }
497
+ }
498
+ ) ;
499
+ const pickFirst = new PickFirstLoadBalancer ( channelControlHelper ) ;
500
+ pickFirst . updateAddressList ( [ { host : 'localhost' , port : 1 } ] , config ) ;
501
+ process . nextTick ( ( ) => {
502
+ subchannels [ 0 ] . transitionToState ( ConnectivityState . TRANSIENT_FAILURE ) ;
503
+ process . nextTick ( ( ) => {
504
+ pickFirst . updateAddressList ( [ { host : 'localhost' , port : 2 } ] , config ) ;
505
+ process . nextTick ( ( ) => {
506
+ subchannels [ 1 ] . transitionToState ( ConnectivityState . TRANSIENT_FAILURE ) ;
507
+ process . nextTick ( ( ) => {
508
+ pickFirst . updateAddressList ( [ { host : 'localhost' , port : 3 } ] , config ) ;
509
+ process . nextTick ( ( ) => {
510
+ subchannels [ 2 ] . transitionToState ( ConnectivityState . TRANSIENT_FAILURE ) ;
511
+ } ) ;
512
+ } ) ;
513
+ } ) ;
514
+ } ) ;
515
+ } ) ;
516
+ } ) ;
517
+ it ( 'Should request reresolution if the new subchannels are already in TF' , done => {
518
+ let reresolutionRequestCount = 0 ;
519
+ const targetReresolutionRequestCount = 3 ;
520
+ const currentStartState = ConnectivityState . TRANSIENT_FAILURE ;
521
+ const channelControlHelper = createChildChannelControlHelper (
522
+ baseChannelControlHelper ,
523
+ {
524
+ createSubchannel : ( subchannelAddress , subchannelArgs ) => {
525
+ const subchannel = new MockSubchannel (
526
+ subchannelAddressToString ( subchannelAddress ) ,
527
+ currentStartState
528
+ ) ;
529
+ subchannels . push ( subchannel ) ;
530
+ return subchannel ;
531
+ } ,
532
+ updateState : updateStateCallBackForExpectedStateSequence (
533
+ [ ConnectivityState . TRANSIENT_FAILURE ] ,
534
+ err => setImmediate ( ( ) => {
535
+ assert . strictEqual ( reresolutionRequestCount , targetReresolutionRequestCount ) ;
536
+ done ( err ) ;
537
+ } )
538
+ ) ,
539
+ requestReresolution : ( ) => {
540
+ reresolutionRequestCount += 1 ;
541
+ }
542
+ }
543
+ ) ;
544
+ const pickFirst = new PickFirstLoadBalancer ( channelControlHelper ) ;
545
+ pickFirst . updateAddressList ( [ { host : 'localhost' , port : 1 } ] , config ) ;
546
+ process . nextTick ( ( ) => {
547
+ pickFirst . updateAddressList ( [ { host : 'localhost' , port : 2 } ] , config ) ;
548
+ process . nextTick ( ( ) => {
549
+ pickFirst . updateAddressList ( [ { host : 'localhost' , port : 2 } ] , config ) ;
550
+ } ) ;
551
+ } ) ;
552
+ } ) ;
465
553
describe ( 'Address list randomization' , ( ) => {
466
554
const shuffleConfig = new PickFirstLoadBalancingConfig ( true ) ;
467
555
it ( 'Should pick different subchannels after multiple updates' , done => {
0 commit comments