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:
Sean McArthur
2018-06-28 12:43:56 -07:00
committed by GitHub
parent 1f95f58837
commit f2d464ac79
6 changed files with 314 additions and 37 deletions

63
src/common/lazy.rs Normal file
View 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"),
}
}
}

View File

@@ -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;