@@ -25,6 +25,18 @@ private static Task<IClient> CreateClient(ClientParameters clientParameters)
25
25
return Task . FromResult < IClient > ( fake ) ;
26
26
}
27
27
28
+ private static IEnumerable < byte > ConsumersIdsPerConnection ( IConsumer consumer )
29
+ {
30
+ var client1 = ( ( RawConsumer ) consumer ) . _client ;
31
+ return client1 . consumers . Keys . ToList ( ) ;
32
+ }
33
+
34
+ private static IEnumerable < byte > ProducersIdsPerConnection ( IProducer producer )
35
+ {
36
+ var client1 = ( ( RawProducer ) producer ) . _client ;
37
+ return client1 . publishers . Keys . ToList ( ) ;
38
+ }
39
+
28
40
private readonly ITestOutputHelper _testOutputHelper ;
29
41
30
42
public ConnectionsPoolTests ( ITestOutputHelper testOutputHelper )
@@ -322,6 +334,7 @@ public async void TwoConsumersShouldShareTheSameConnectionFromThePool()
322
334
323
335
await client . DeleteStream ( Stream1 ) ;
324
336
await client . DeleteStream ( Stream2 ) ;
337
+ await client . Close ( "byte" ) ;
325
338
}
326
339
327
340
/// <summary>
@@ -364,6 +377,7 @@ public async void TwoProducersShouldShareTheSameConnectionFromThePool()
364
377
365
378
await client . DeleteStream ( Stream1 ) ;
366
379
await client . DeleteStream ( Stream2 ) ;
380
+ await client . Close ( "byte" ) ;
367
381
}
368
382
369
383
/// <summary>
@@ -391,19 +405,34 @@ public async void TwoProducerAndConsumerShouldHaveDifferentConnection()
391
405
Assert . Equal ( 1 , pool . ActiveIdsCountForStream ( Stream1 ) ) ;
392
406
Assert . Equal ( 1 , pool . ActiveIdsCountForStream ( Stream2 ) ) ;
393
407
408
+ Assert . NotEmpty ( ProducersIdsPerConnection ( p2 ) . ToList ( ) ) ;
409
+ Assert . Equal ( 0 , ProducersIdsPerConnection ( p2 ) . ToList ( ) [ 0 ] ) ;
410
+
411
+ Assert . NotEmpty ( ConsumersIdsPerConnection ( c1 ) . ToList ( ) ) ;
412
+ Assert . Equal ( 0 , ConsumersIdsPerConnection ( c1 ) . ToList ( ) [ 0 ] ) ;
413
+
394
414
Assert . Equal ( ResponseCode . Ok , await c1 . Close ( ) ) ;
395
415
// closing should be idempotent and not affect to the pool
396
416
Assert . Equal ( ResponseCode . Ok , await c1 . Close ( ) ) ;
397
417
398
418
Assert . Equal ( 1 , pool . ConnectionsCount ) ;
399
419
Assert . Equal ( 0 , pool . ActiveIdsCountForStream ( Stream1 ) ) ;
400
420
421
+ Assert . NotEmpty ( ProducersIdsPerConnection ( p2 ) . ToList ( ) ) ;
422
+ Assert . Equal ( 0 , ProducersIdsPerConnection ( p2 ) . ToList ( ) [ 0 ] ) ;
423
+
424
+ Assert . Empty ( ConsumersIdsPerConnection ( c1 ) . ToList ( ) ) ;
425
+
401
426
await p2 . Close ( ) ;
402
427
Assert . Equal ( 0 , pool . ConnectionsCount ) ;
403
428
Assert . Equal ( 0 , pool . ActiveIdsCountForStream ( Stream2 ) ) ;
404
429
430
+ Assert . Empty ( ProducersIdsPerConnection ( p2 ) . ToList ( ) ) ;
431
+ Assert . Empty ( ConsumersIdsPerConnection ( c1 ) . ToList ( ) ) ;
432
+
405
433
await client . DeleteStream ( Stream1 ) ;
406
434
await client . DeleteStream ( Stream2 ) ;
435
+ await client . Close ( "byte" ) ;
407
436
}
408
437
409
438
/// <summary>
@@ -470,6 +499,7 @@ await RawConsumer.Create(client.Parameters,
470
499
Assert . Equal ( msgDataStream2 . Contents . ToArray ( ) , testPassedC2 . Task . Result . Contents . ToArray ( ) ) ;
471
500
await client . DeleteStream ( Stream1 ) ;
472
501
await client . DeleteStream ( Stream2 ) ;
502
+ await client . Close ( "byte" ) ;
473
503
}
474
504
475
505
/// <summary>
@@ -496,13 +526,17 @@ await Assert.ThrowsAsync<AggregateException>(async () => await RawConsumer.Creat
496
526
Assert . Equal ( 1 , pool . ConnectionsCount ) ;
497
527
Assert . Equal ( 1 , pool . ActiveIdsCountForStream ( Stream2 ) ) ;
498
528
Assert . Equal ( 1 , pool . ActiveIdsCount ) ;
529
+ Assert . NotEmpty ( ProducersIdsPerConnection ( p1 ) . ToList ( ) ) ;
530
+ Assert . Equal ( 0 , ProducersIdsPerConnection ( p1 ) . ToList ( ) [ 0 ] ) ;
499
531
500
532
await p1 . Close ( ) ;
501
533
Assert . Equal ( 0 , pool . ConnectionsCount ) ;
502
534
Assert . Equal ( 0 , pool . ActiveIdsCount ) ;
535
+ Assert . Empty ( ProducersIdsPerConnection ( p1 ) . ToList ( ) ) ;
503
536
504
537
await client . DeleteStream ( Stream1 ) ;
505
538
await client . DeleteStream ( Stream2 ) ;
539
+ await client . Close ( "byte" ) ;
506
540
}
507
541
508
542
/// <summary>
@@ -524,7 +558,7 @@ public async void TheProducerPoolShouldBeConsistentInMultiThread()
524
558
var producerList = new ConcurrentDictionary < string , IProducer > ( ) ;
525
559
526
560
var tasksP = new List < Task > ( ) ;
527
- for ( var i = 0 ; i < ( IdsPerConnection * 2 ) ; i ++ )
561
+ for ( var i = 0 ; i < ( IdsPerConnection ) ; i ++ )
528
562
{
529
563
tasksP . Add ( Task . Run ( async ( ) =>
530
564
{
@@ -536,6 +570,21 @@ public async void TheProducerPoolShouldBeConsistentInMultiThread()
536
570
537
571
await Task . WhenAll ( tasksP ) ;
538
572
573
+ producerList . Values . ToList ( ) . ForEach ( p => Assert . Equal ( IdsPerConnection , ProducersIdsPerConnection ( p ) . Count ( ) ) ) ;
574
+
575
+ for ( var i = 0 ; i < ( IdsPerConnection ) ; i ++ )
576
+ {
577
+ tasksP . Add ( Task . Run ( async ( ) =>
578
+ {
579
+ var p = await RawProducer . Create ( client . Parameters , new RawProducerConfig ( Stream1 ) { Pool = pool } ,
580
+ metaDataInfo . StreamInfos [ Stream1 ] ) ;
581
+ producerList . TryAdd ( Guid . NewGuid ( ) . ToString ( ) , p ) ;
582
+ } ) ) ;
583
+ }
584
+
585
+ await Task . WhenAll ( tasksP ) ;
586
+ producerList . Values . ToList ( ) . ForEach ( p => Assert . Equal ( IdsPerConnection , ProducersIdsPerConnection ( p ) . Count ( ) ) ) ;
587
+
539
588
Assert . Equal ( 2 , pool . ConnectionsCount ) ;
540
589
Assert . Equal ( IdsPerConnection * 2 , pool . ActiveIdsCountForStream ( Stream1 ) ) ;
541
590
@@ -549,6 +598,7 @@ public async void TheProducerPoolShouldBeConsistentInMultiThread()
549
598
Assert . Equal ( 0 , pool . ConnectionsCount ) ;
550
599
Assert . Equal ( 0 , pool . ActiveIdsCount ) ;
551
600
await client . DeleteStream ( Stream1 ) ;
601
+ await client . Close ( "byte" ) ;
552
602
}
553
603
554
604
/// <summary>
@@ -592,6 +642,7 @@ public async void TheProducerConsumerPoolShouldBeConsistentInMultiThreadCreateDe
592
642
Assert . Equal ( 0 , pool . ConnectionsCount ) ;
593
643
Assert . Equal ( 0 , pool . ActiveIdsCount ) ;
594
644
await client . DeleteStream ( Stream1 ) ;
645
+ await client . Close ( "byte" ) ;
595
646
}
596
647
597
648
// // this test doesn't work since the client parameters metadata handler is not an event
@@ -681,33 +732,97 @@ await RawConsumer.Create(client.Parameters,
681
732
Assert . Equal ( 0 , pool . ActiveIdsCount ) ;
682
733
Assert . Equal ( 0 , pool . ConnectionsCount ) ;
683
734
await client . DeleteStream ( Stream1 ) ;
735
+ await client . Close ( "byte" ) ;
736
+ }
737
+
738
+ [ Fact ]
739
+ public async void TheConsumerPoolShouldBeConsistentWhenTheConnectionIsClosed ( )
740
+ {
741
+ var clientProvidedName = Guid . NewGuid ( ) . ToString ( ) ;
742
+ var client = await Client . Create ( new ClientParameters ( ) { ClientProvidedName = clientProvidedName } ) ;
743
+ const string Stream1 = "pool_test_stream_1_test_connection_closed" ;
744
+ const string Stream2 = "pool_test_stream_2_test_connection_closed" ;
745
+ await client . CreateStream ( Stream1 , new Dictionary < string , string > ( ) ) ;
746
+ await client . CreateStream ( Stream2 , new Dictionary < string , string > ( ) ) ;
747
+ const int IdsPerConnection = 2 ;
748
+ var pool = new ConnectionsPool ( 0 , IdsPerConnection ) ;
749
+ var metaDataInfo = await client . QueryMetadata ( new [ ] { Stream1 , Stream2 } ) ;
750
+
751
+ var c1 = await RawConsumer . Create ( client . Parameters ,
752
+ new RawConsumerConfig ( Stream1 ) { Pool = pool } ,
753
+ metaDataInfo . StreamInfos [ Stream1 ] ) ;
754
+
755
+ var c2 = await RawConsumer . Create ( client . Parameters ,
756
+ new RawConsumerConfig ( Stream2 ) { Pool = pool } ,
757
+ metaDataInfo . StreamInfos [ Stream2 ] ) ;
758
+
759
+ Assert . Equal ( 1 , pool . ConnectionsCount ) ;
760
+ SystemUtils . WaitUntil ( ( ) => SystemUtils . HttpKillConnections ( clientProvidedName ) . Result == 2 ) ;
761
+ SystemUtils . WaitUntil ( ( ) => pool . ConnectionsCount == 0 ) ;
762
+ Assert . Equal ( 0 , pool . ConnectionsCount ) ;
763
+ Assert . Equal ( 0 , pool . ActiveIdsCount ) ;
764
+ Assert . Equal ( 0 , pool . ActiveIdsCountForStream ( Stream1 ) ) ;
765
+ Assert . Equal ( 0 , pool . ActiveIdsCountForStream ( Stream2 ) ) ;
766
+ SystemUtils . Wait ( ) ; // the event close is raised in another thread so we need to wait a bit to be sure the event is raised
767
+ Assert . Empty ( ConsumersIdsPerConnection ( c1 ) . ToList ( ) ) ;
768
+ Assert . Empty ( ConsumersIdsPerConnection ( c2 ) . ToList ( ) ) ;
769
+
770
+ client = await Client . Create ( new ClientParameters ( ) ) ;
771
+ await client . DeleteStream ( Stream1 ) ;
772
+ await client . DeleteStream ( Stream2 ) ;
773
+ await client . Close ( "bye" ) ;
684
774
}
685
775
686
776
/// The following tests are related to the FindMissingConsecutive method
687
777
/// We need to find the missing consecutive ids
688
778
/// by protocol we can have multi ids per connection so we need to find the missing ids
689
779
/// in case one id is released from the pool
690
780
/// if we start with 0,1,2,3,4,5,6,7,8,9 at some point we release the id 3
691
- /// the next id should be 3
692
- /// the id is a byte so we can have 0-255
781
+ /// the nextid it will be still 10
782
+ /// The FindNextValidId function will start to reuse the missing ids when the max is reached
783
+ /// In this way we can reduce the time to use the same ids
693
784
[ Fact ]
694
- public void FindMissingConsecutiveShouldReturnZeroGivenEmptyList ( )
785
+ public void FindNextValidIdShouldReturnZeroGivenEmptyList ( )
695
786
{
696
787
var ids = new List < byte > ( ) ;
697
- var missing = ConnectionsPool . FindMissingConsecutive ( ids ) ;
788
+ var missing = ConnectionsPool . FindNextValidId ( ids ) ;
698
789
Assert . Equal ( 0 , missing ) ;
699
790
}
700
791
701
792
[ Fact ]
702
- public void FindMissingConsecutiveShouldReturnOneGivenOneItem ( )
793
+ public void FindNextValidIdShouldReturnOne ( )
703
794
{
704
795
var ids = new List < byte > ( ) { 0 } ;
705
- var missing = ConnectionsPool . FindMissingConsecutive ( ids ) ;
796
+ var missing = ConnectionsPool . FindNextValidId ( ids ) ;
706
797
Assert . Equal ( 1 , missing ) ;
707
798
}
708
799
800
+ // even there are missing ids the next valid id is the next one
801
+ [ Fact ]
802
+ public void FindNextValidShouldReturnTreeGivenAList ( )
803
+ {
804
+ var ids = new List < byte > ( )
805
+ {
806
+ 0 ,
807
+ 1 ,
808
+ 2 ,
809
+ 4 ,
810
+ 6 ,
811
+ 8 ,
812
+ 9
813
+ } ;
814
+ var nextValidId = ConnectionsPool . FindNextValidId ( ids ) ;
815
+ Assert . Equal ( 10 , nextValidId ) ;
816
+ ids . Add ( 10 ) ;
817
+ nextValidId = ConnectionsPool . FindNextValidId ( ids ) ;
818
+ Assert . Equal ( 11 , nextValidId ) ;
819
+ ids . Add ( 11 ) ;
820
+ }
821
+
822
+ // in this case we start to recycle the ids
823
+ // since the max is reached
709
824
[ Fact ]
710
- public void FindMissingConsecutiveShouldReturnTreeGivenAList ( )
825
+ public void RecycleIdsWhenTheMaxIsReached ( )
711
826
{
712
827
var ids = new List < byte > ( )
713
828
{
@@ -722,19 +837,26 @@ public void FindMissingConsecutiveShouldReturnTreeGivenAList()
722
837
8 ,
723
838
9
724
839
} ;
725
- var missing = ConnectionsPool . FindMissingConsecutive ( ids ) ;
726
- Assert . Equal ( 3 , missing ) ;
840
+ for ( byte i = 10 ; i < byte . MaxValue ; i ++ )
841
+ {
842
+ ids . Add ( i ) ;
843
+ }
844
+
845
+ var nextValidId = ConnectionsPool . FindNextValidId ( ids ) ;
846
+ Assert . Equal ( 255 , nextValidId ) ;
847
+ ids . Add ( 255 ) ;
848
+
849
+ nextValidId = ConnectionsPool . FindNextValidId ( ids ) ;
850
+ Assert . Equal ( 3 , nextValidId ) ;
727
851
ids . Add ( 3 ) ;
728
- missing = ConnectionsPool . FindMissingConsecutive ( ids ) ;
729
- Assert . Equal ( 5 , missing ) ;
730
852
853
+ nextValidId = ConnectionsPool . FindNextValidId ( ids ) ;
854
+ Assert . Equal ( 5 , nextValidId ) ;
731
855
ids . Add ( 5 ) ;
732
- missing = ConnectionsPool . FindMissingConsecutive ( ids ) ;
733
- Assert . Equal ( 7 , missing ) ;
734
856
857
+ nextValidId = ConnectionsPool . FindNextValidId ( ids ) ;
858
+ Assert . Equal ( 7 , nextValidId ) ;
735
859
ids . Add ( 7 ) ;
736
- missing = ConnectionsPool . FindMissingConsecutive ( ids ) ;
737
- Assert . Equal ( 10 , missing ) ;
738
860
}
739
861
}
740
862
}
0 commit comments