@@ -44,7 +44,7 @@ use std::{
44
44
io:: { self , Write } ,
45
45
sync:: {
46
46
atomic:: { AtomicUsize , Ordering } ,
47
- Arc ,
47
+ Arc , RwLock ,
48
48
} ,
49
49
time:: Duration ,
50
50
} ;
@@ -348,7 +348,7 @@ impl Transport {
348
348
. iter ( )
349
349
. map ( |url| Url :: parse ( url) )
350
350
. collect :: < Result < Vec < _ > , _ > > ( ) ?;
351
- let conn_pool = StaticNodeListConnectionPool :: round_robin ( urls) ;
351
+ let conn_pool = MultiNodeConnectionPool :: round_robin ( urls) ;
352
352
let transport = TransportBuilder :: new ( conn_pool) . build ( ) ?;
353
353
Ok ( transport)
354
354
}
@@ -461,7 +461,7 @@ impl Default for Transport {
461
461
/// dynamically at runtime, based upon the response to API calls.
462
462
pub trait ConnectionPool : Debug + dyn_clone:: DynClone + Sync + Send {
463
463
/// Gets a reference to the next [Connection]
464
- fn next ( & self ) -> & Connection ;
464
+ fn next ( & self ) -> Connection ;
465
465
}
466
466
467
467
clone_trait_object ! ( ConnectionPool ) ;
@@ -490,8 +490,8 @@ impl Default for SingleNodeConnectionPool {
490
490
491
491
impl ConnectionPool for SingleNodeConnectionPool {
492
492
/// Gets a reference to the next [Connection]
493
- fn next ( & self ) -> & Connection {
494
- & self . connection
493
+ fn next ( & self ) -> Connection {
494
+ self . connection . clone ( )
495
495
}
496
496
}
497
497
@@ -611,31 +611,33 @@ impl CloudConnectionPool {
611
611
612
612
impl ConnectionPool for CloudConnectionPool {
613
613
/// Gets a reference to the next [Connection]
614
- fn next ( & self ) -> & Connection {
615
- & self . connection
614
+ fn next ( & self ) -> Connection {
615
+ self . connection . clone ( )
616
616
}
617
617
}
618
618
619
619
/// A Connection Pool that manages a static connection of nodes
620
620
#[ derive( Debug , Clone ) ]
621
- pub struct StaticNodeListConnectionPool < TStrategy = RoundRobin > {
622
- connections : Vec < Connection > ,
621
+ pub struct MultiNodeConnectionPool < TStrategy = RoundRobin > {
622
+ connections : Arc < RwLock < Vec < Connection > > > ,
623
623
strategy : TStrategy ,
624
624
}
625
625
626
- impl < TStrategy > ConnectionPool for StaticNodeListConnectionPool < TStrategy >
626
+ impl < TStrategy > ConnectionPool for MultiNodeConnectionPool < TStrategy >
627
627
where
628
628
TStrategy : Strategy + Clone ,
629
629
{
630
- fn next ( & self ) -> & Connection {
631
- self . strategy . try_next ( & self . connections ) . unwrap ( )
630
+ fn next ( & self ) -> Connection {
631
+ let inner = self . connections . read ( ) . expect ( "lock poisoned" ) ;
632
+ self . strategy . try_next ( & inner) . unwrap ( )
632
633
}
633
634
}
634
635
635
- impl StaticNodeListConnectionPool < RoundRobin > {
636
+ impl MultiNodeConnectionPool < RoundRobin > {
636
637
/** Use a round-robin strategy for balancing traffic over the given set of nodes. */
637
638
pub fn round_robin ( urls : Vec < Url > ) -> Self {
638
- let connections: Vec < _ > = urls. into_iter ( ) . map ( Connection :: new) . collect ( ) ;
639
+ let connections: Arc < RwLock < Vec < _ > > > =
640
+ Arc :: new ( RwLock :: new ( urls. into_iter ( ) . map ( Connection :: new) . collect ( ) ) ) ;
639
641
640
642
let strategy = RoundRobin :: default ( ) ;
641
643
@@ -649,7 +651,7 @@ impl StaticNodeListConnectionPool<RoundRobin> {
649
651
/** The strategy selects an address from a given collection. */
650
652
pub trait Strategy : Send + Sync + Debug {
651
653
/** Try get the next connection. */
652
- fn try_next < ' a > ( & self , connections : & ' a [ Connection ] ) -> Result < & ' a Connection , Error > ;
654
+ fn try_next < ' a > ( & self , connections : & ' a [ Connection ] ) -> Result < Connection , Error > ;
653
655
}
654
656
655
657
/** A round-robin strategy cycles through nodes sequentially. */
@@ -667,12 +669,12 @@ impl Default for RoundRobin {
667
669
}
668
670
669
671
impl Strategy for RoundRobin {
670
- fn try_next < ' a > ( & self , connections : & ' a [ Connection ] ) -> Result < & ' a Connection , Error > {
672
+ fn try_next < ' a > ( & self , connections : & ' a [ Connection ] ) -> Result < Connection , Error > {
671
673
if connections. is_empty ( ) {
672
674
Err ( crate :: error:: lib ( "Connection list empty" ) )
673
675
} else {
674
676
let i = self . index . fetch_add ( 1 , Ordering :: Relaxed ) % connections. len ( ) ;
675
- Ok ( & connections[ i] )
677
+ Ok ( connections[ i] . clone ( ) )
676
678
}
677
679
}
678
680
}
@@ -682,8 +684,8 @@ pub mod tests {
682
684
#[ cfg( any( feature = "native-tls" , feature = "rustls-tls" ) ) ]
683
685
use crate :: auth:: ClientCertificate ;
684
686
use crate :: http:: transport:: {
685
- CloudId , Connection , ConnectionPool , RoundRobin , SingleNodeConnectionPool ,
686
- StaticNodeListConnectionPool , TransportBuilder ,
687
+ CloudId , Connection , ConnectionPool , MultiNodeConnectionPool , RoundRobin ,
688
+ SingleNodeConnectionPool , TransportBuilder ,
687
689
} ;
688
690
use url:: Url ;
689
691
@@ -795,8 +797,8 @@ pub mod tests {
795
797
assert_eq ! ( conn. url. as_str( ) , "http://10.1.2.3/" ) ;
796
798
}
797
799
798
- fn round_robin ( addresses : Vec < Url > ) -> StaticNodeListConnectionPool < RoundRobin > {
799
- StaticNodeListConnectionPool :: round_robin ( addresses)
800
+ fn round_robin ( addresses : Vec < Url > ) -> MultiNodeConnectionPool < RoundRobin > {
801
+ MultiNodeConnectionPool :: round_robin ( addresses)
800
802
}
801
803
802
804
fn expected_addresses ( ) -> Vec < Url > {
0 commit comments