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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user