fix(client): try to reuse connections when pool checkout wins
If a checkout wins, meaning an idle connection became available before a connect future completed, instead of just dropping the connect future, it spawns it into the background executor to allow being placed into the pool on completion.
This commit is contained in:
		
							
								
								
									
										63
									
								
								src/common/lazy.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								src/common/lazy.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| use std::mem; | ||||
|  | ||||
| use futures::{Future, IntoFuture, Poll}; | ||||
|  | ||||
| pub(crate) fn lazy<F, R>(func: F) -> Lazy<F, R> | ||||
| where | ||||
|     F: FnOnce() -> R, | ||||
|     R: IntoFuture, | ||||
| { | ||||
|     Lazy { | ||||
|         inner: Inner::Init(func), | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub struct Lazy<F, R: IntoFuture> { | ||||
|     inner: Inner<F, R::Future> | ||||
| } | ||||
|  | ||||
| enum Inner<F, R> { | ||||
|     Init(F), | ||||
|     Fut(R), | ||||
|     Empty, | ||||
| } | ||||
|  | ||||
| impl<F, R> Lazy<F, R> | ||||
| where | ||||
|     F: FnOnce() -> R, | ||||
|     R: IntoFuture, | ||||
| { | ||||
|     pub fn started(&self) -> bool { | ||||
|         match self.inner { | ||||
|             Inner::Init(_) => false, | ||||
|             Inner::Fut(_) | | ||||
|             Inner::Empty => true, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<F, R> Future for Lazy<F, R> | ||||
| where | ||||
|     F: FnOnce() -> R, | ||||
|     R: IntoFuture, | ||||
| { | ||||
|     type Item = R::Item; | ||||
|     type Error = R::Error; | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|         match self.inner { | ||||
|             Inner::Fut(ref mut f) => return f.poll(), | ||||
|             _ => (), | ||||
|         } | ||||
|  | ||||
|         match mem::replace(&mut self.inner, Inner::Empty) { | ||||
|             Inner::Init(func) => { | ||||
|                 let mut fut = func().into_future(); | ||||
|                 let ret = fut.poll(); | ||||
|                 self.inner = Inner::Fut(fut); | ||||
|                 ret | ||||
|             }, | ||||
|             _ => unreachable!("lazy state wrong"), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,8 +1,10 @@ | ||||
| mod buf; | ||||
| mod exec; | ||||
| pub(crate) mod io; | ||||
| mod lazy; | ||||
| mod never; | ||||
|  | ||||
| pub(crate) use self::buf::StaticBuf; | ||||
| pub(crate) use self::exec::Exec; | ||||
| pub(crate) use self::lazy::lazy; | ||||
| pub use self::never::Never; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user