@@ -46,7 +46,7 @@ use std::{
46
46
atomic:: { AtomicUsize , Ordering } ,
47
47
Arc , RwLock ,
48
48
} ,
49
- time:: Duration ,
49
+ time:: { Duration , Instant } ,
50
50
} ;
51
51
use url:: Url ;
52
52
@@ -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 = MultiNodeConnectionPool :: round_robin ( urls) ;
351
+ let conn_pool = MultiNodeConnectionPool :: round_robin ( urls, None ) ;
352
352
let transport = TransportBuilder :: new ( conn_pool) . build ( ) ?;
353
353
Ok ( transport)
354
354
}
@@ -379,6 +379,10 @@ impl Transport {
379
379
B : Body ,
380
380
Q : Serialize + ?Sized ,
381
381
{
382
+ if self . conn_pool . reseedable ( ) {
383
+ // Reseed nodes
384
+ println ! ( "Reseeding!" ) ;
385
+ }
382
386
let connection = self . conn_pool . next ( ) ;
383
387
let url = connection. url . join ( path. trim_start_matches ( '/' ) ) ?;
384
388
let reqwest_method = self . method ( method) ;
@@ -462,6 +466,13 @@ impl Default for Transport {
462
466
pub trait ConnectionPool : Debug + dyn_clone:: DynClone + Sync + Send {
463
467
/// Gets a reference to the next [Connection]
464
468
fn next ( & self ) -> Connection ;
469
+
470
+ fn reseedable ( & self ) -> bool {
471
+ false
472
+ }
473
+
474
+ // NOOP by default
475
+ fn reseed ( & self , _connection : Vec < Connection > ) { }
465
476
}
466
477
467
478
clone_trait_object ! ( ConnectionPool ) ;
@@ -619,31 +630,63 @@ impl ConnectionPool for CloudConnectionPool {
619
630
/// A Connection Pool that manages a static connection of nodes
620
631
#[ derive( Debug , Clone ) ]
621
632
pub struct MultiNodeConnectionPool < TStrategy = RoundRobin > {
622
- connections : Arc < RwLock < Vec < Connection > > > ,
633
+ inner : Arc < RwLock < MultiNodeConnectionPoolInner > > ,
634
+ wait : Option < Duration > ,
623
635
strategy : TStrategy ,
624
636
}
625
637
638
+ #[ derive( Debug , Clone ) ]
639
+ pub struct MultiNodeConnectionPoolInner {
640
+ last_update : Option < Instant > ,
641
+ connections : Vec < Connection > ,
642
+ }
643
+
626
644
impl < TStrategy > ConnectionPool for MultiNodeConnectionPool < TStrategy >
627
645
where
628
646
TStrategy : Strategy + Clone ,
629
647
{
630
648
fn next ( & self ) -> Connection {
631
- let inner = self . connections . read ( ) . expect ( "lock poisoned" ) ;
632
- self . strategy . try_next ( & inner) . unwrap ( )
649
+ let inner = self . inner . read ( ) . expect ( "lock poisoned" ) ;
650
+ self . strategy . try_next ( & inner. connections ) . unwrap ( )
651
+ }
652
+
653
+ fn reseedable ( & self ) -> bool {
654
+ let inner = self . inner . read ( ) . expect ( "lock poisoned" ) ;
655
+ let wait = match self . wait {
656
+ Some ( wait) => wait,
657
+ None => return false ,
658
+ } ;
659
+ let last_update_is_stale = inner
660
+ . last_update
661
+ . as_ref ( )
662
+ . map ( |last_update| last_update. elapsed ( ) > wait) ;
663
+ last_update_is_stale. unwrap_or ( true )
664
+ }
665
+
666
+ fn reseed ( & self , mut connection : Vec < Connection > ) {
667
+ let mut inner = self . inner . write ( ) . expect ( "lock poisoned" ) ;
668
+ inner. last_update = Some ( Instant :: now ( ) ) ;
669
+ inner. connections . clear ( ) ;
670
+ inner. connections . append ( & mut connection) ;
633
671
}
634
672
}
635
673
636
674
impl MultiNodeConnectionPool < RoundRobin > {
637
675
/** Use a round-robin strategy for balancing traffic over the given set of nodes. */
638
- pub fn round_robin ( urls : Vec < Url > ) -> Self {
639
- let connections: Arc < RwLock < Vec < _ > > > =
640
- Arc :: new ( RwLock :: new ( urls. into_iter ( ) . map ( Connection :: new) . collect ( ) ) ) ;
676
+ pub fn round_robin ( urls : Vec < Url > , wait : Option < Duration > ) -> Self {
677
+ let connections = urls. into_iter ( ) . map ( Connection :: new) . collect ( ) ;
641
678
642
- let strategy = RoundRobin :: default ( ) ;
679
+ let inner: Arc < RwLock < MultiNodeConnectionPoolInner > > =
680
+ Arc :: new ( RwLock :: new ( MultiNodeConnectionPoolInner {
681
+ last_update : None ,
682
+ connections,
683
+ } ) ) ;
643
684
685
+ let strategy = RoundRobin :: default ( ) ;
644
686
Self {
645
- connections ,
687
+ inner ,
646
688
strategy,
689
+ wait,
647
690
}
648
691
}
649
692
}
0 commit comments