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