@@ -15,9 +15,13 @@ use std::task::{self, Poll};
15
15
use std:: time:: { Duration , Instant } ;
16
16
17
17
use futures_channel:: oneshot;
18
+ use futures_util:: ready;
18
19
use tracing:: { debug, trace} ;
19
20
20
- use crate :: common:: { exec, exec:: Exec , ready} ;
21
+ use hyper:: rt:: Sleep ;
22
+ use hyper:: rt:: Timer as _;
23
+
24
+ use crate :: common:: { exec, exec:: Exec , timer:: Timer } ;
21
25
22
26
// FIXME: allow() required due to `impl Trait` leaking types to this lint
23
27
#[ allow( missing_debug_implementations) ]
@@ -96,6 +100,7 @@ struct PoolInner<T, K: Eq + Hash> {
96
100
// the Pool completely drops. That way, the interval can cancel immediately.
97
101
idle_interval_ref : Option < oneshot:: Sender < Infallible > > ,
98
102
exec : Exec ,
103
+ timer : Option < Timer > ,
99
104
timeout : Option < Duration > ,
100
105
}
101
106
@@ -116,11 +121,13 @@ impl Config {
116
121
}
117
122
118
123
impl < T , K : Key > Pool < T , K > {
119
- pub fn new < E > ( config : Config , executor : E ) -> Pool < T , K >
124
+ pub fn new < E , M > ( config : Config , executor : E , timer : Option < M > ) -> Pool < T , K >
120
125
where
121
126
E : hyper:: rt:: Executor < exec:: BoxSendFuture > + Send + Sync + Clone + ' static ,
127
+ M : hyper:: rt:: Timer + Send + Sync + Clone + ' static ,
122
128
{
123
129
let exec = Exec :: new ( executor) ;
130
+ let timer = timer. map ( |t| Timer :: new ( t) ) ;
124
131
let inner = if config. is_enabled ( ) {
125
132
Some ( Arc :: new ( Mutex :: new ( PoolInner {
126
133
connecting : HashSet :: new ( ) ,
@@ -129,6 +136,7 @@ impl<T, K: Key> Pool<T, K> {
129
136
max_idle_per_host : config. max_idle_per_host ,
130
137
waiters : HashMap :: new ( ) ,
131
138
exec,
139
+ timer,
132
140
timeout : config. idle_timeout ,
133
141
} ) ) )
134
142
} else {
@@ -380,7 +388,7 @@ impl<T: Poolable, K: Key> PoolInner<T, K> {
380
388
Some ( value) => {
381
389
// borrow-check scope...
382
390
{
383
- let idle_list = self . idle . entry ( key. clone ( ) ) . or_insert_with ( Vec :: new ) ;
391
+ let idle_list = self . idle . entry ( key. clone ( ) ) . or_default ( ) ;
384
392
if self . max_idle_per_host <= idle_list. len ( ) {
385
393
trace ! ( "max idle per host for {:?}, dropping connection" , key) ;
386
394
return ;
@@ -410,31 +418,33 @@ impl<T: Poolable, K: Key> PoolInner<T, K> {
410
418
self . waiters . remove ( key) ;
411
419
}
412
420
413
- fn spawn_idle_interval ( & mut self , _pool_ref : & Arc < Mutex < PoolInner < T , K > > > ) {
414
- // TODO
415
- /*
416
- let (dur, rx) = {
417
- if self.idle_interval_ref.is_some() {
418
- return;
419
- }
420
-
421
- if let Some(dur) = self.timeout {
422
- let (tx, rx) = oneshot::channel();
423
- self.idle_interval_ref = Some(tx);
424
- (dur, rx)
425
- } else {
426
- return;
427
- }
421
+ fn spawn_idle_interval ( & mut self , pool_ref : & Arc < Mutex < PoolInner < T , K > > > ) {
422
+ if self . idle_interval_ref . is_some ( ) {
423
+ return ;
424
+ }
425
+ let dur = if let Some ( dur) = self . timeout {
426
+ dur
427
+ } else {
428
+ return ;
429
+ } ;
430
+ let timer = if let Some ( timer) = self . timer . clone ( ) {
431
+ timer
432
+ } else {
433
+ return ;
428
434
} ;
435
+ let ( tx, rx) = oneshot:: channel ( ) ;
436
+ self . idle_interval_ref = Some ( tx) ;
429
437
430
438
let interval = IdleTask {
431
- interval: tokio::time::interval(dur),
439
+ timer : timer. clone ( ) ,
440
+ duration : dur,
441
+ deadline : Instant :: now ( ) ,
442
+ fut : timer. sleep_until ( Instant :: now ( ) ) , // ready at first tick
432
443
pool : WeakOpt :: downgrade ( pool_ref) ,
433
444
pool_drop_notifier : rx,
434
445
} ;
435
446
436
447
self . exec . execute ( interval) ;
437
- */
438
448
}
439
449
}
440
450
@@ -754,11 +764,12 @@ impl Expiration {
754
764
}
755
765
}
756
766
757
- /*
758
767
pin_project_lite:: pin_project! {
759
768
struct IdleTask <T , K : Key > {
760
- #[pin]
761
- interval: Interval,
769
+ timer: Timer ,
770
+ duration: Duration ,
771
+ deadline: Instant ,
772
+ fut: Pin <Box <dyn Sleep >>,
762
773
pool: WeakOpt <Mutex <PoolInner <T , K >>>,
763
774
// This allows the IdleTask to be notified as soon as the entire
764
775
// Pool is fully dropped, and shutdown. This channel is never sent on,
@@ -783,7 +794,15 @@ impl<T: Poolable + 'static, K: Key> Future for IdleTask<T, K> {
783
794
}
784
795
}
785
796
786
- ready!(this.interval.as_mut().poll_tick(cx));
797
+ ready ! ( Pin :: new( & mut this. fut) . poll( cx) ) ;
798
+ // Set this task to run after the next deadline
799
+ // If the poll missed the deadline by a lot, set the deadline
800
+ // from the current time instead
801
+ * this. deadline = * this. deadline + * this. duration ;
802
+ if * this. deadline < Instant :: now ( ) - Duration :: from_millis ( 5 ) {
803
+ * this. deadline = Instant :: now ( ) + * this. duration ;
804
+ }
805
+ * this. fut = this. timer . sleep_until ( * this. deadline ) ;
787
806
788
807
if let Some ( inner) = this. pool . upgrade ( ) {
789
808
if let Ok ( mut inner) = inner. lock ( ) {
@@ -796,7 +815,6 @@ impl<T: Poolable + 'static, K: Key> Future for IdleTask<T, K> {
796
815
}
797
816
}
798
817
}
799
- */
800
818
801
819
impl < T > WeakOpt < T > {
802
820
fn none ( ) -> Self {
@@ -822,7 +840,9 @@ mod tests {
822
840
use std:: time:: Duration ;
823
841
824
842
use super :: { Connecting , Key , Pool , Poolable , Reservation , WeakOpt } ;
825
- use crate :: rt:: TokioExecutor ;
843
+ use crate :: rt:: { TokioExecutor , TokioTimer } ;
844
+
845
+ use crate :: common:: timer;
826
846
827
847
#[ derive( Clone , Debug , PartialEq , Eq , Hash ) ]
828
848
struct KeyImpl ( http:: uri:: Scheme , http:: uri:: Authority ) ;
@@ -869,6 +889,7 @@ mod tests {
869
889
max_idle_per_host : max_idle,
870
890
} ,
871
891
TokioExecutor :: new ( ) ,
892
+ Option :: < timer:: Timer > :: None ,
872
893
) ;
873
894
pool. no_timer ( ) ;
874
895
pool
@@ -959,16 +980,14 @@ mod tests {
959
980
}
960
981
961
982
#[ tokio:: test]
962
- #[ ignore] // TODO
963
983
async fn test_pool_timer_removes_expired ( ) {
964
- tokio:: time:: pause ( ) ;
965
-
966
984
let pool = Pool :: new (
967
985
super :: Config {
968
986
idle_timeout : Some ( Duration :: from_millis ( 10 ) ) ,
969
987
max_idle_per_host : std:: usize:: MAX ,
970
988
} ,
971
989
TokioExecutor :: new ( ) ,
990
+ Some ( TokioTimer :: new ( ) ) ,
972
991
) ;
973
992
974
993
let key = host_key ( "foo" ) ;
@@ -983,7 +1002,7 @@ mod tests {
983
1002
) ;
984
1003
985
1004
// Let the timer tick passed the expiration...
986
- tokio:: time:: advance ( Duration :: from_millis ( 30 ) ) . await ;
1005
+ tokio:: time:: sleep ( Duration :: from_millis ( 30 ) ) . await ;
987
1006
// Yield so the Interval can reap...
988
1007
tokio:: task:: yield_now ( ) . await ;
989
1008
0 commit comments