Skip to content

Commit b0c1320

Browse files
committed
refactor(client): change retryable request future from boxed to 'impl Future'
1 parent 192348d commit b0c1320

File tree

1 file changed

+35
-64
lines changed

1 file changed

+35
-64
lines changed

src/client/mod.rs

Lines changed: 35 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -247,25 +247,45 @@ where C: Connect + Sync + 'static,
247247
}
248248

249249

250+
let pool_key = (Arc::new(domain.to_string()), self.ver);
251+
ResponseFuture::new(Box::new(self.retryably_send_request(req, pool_key)))
252+
}
253+
254+
fn retryably_send_request(&self, req: Request<B>, pool_key: PoolKey) -> impl Future<Item=Response<Body>, Error=::Error> {
250255
let client = self.clone();
251256
let uri = req.uri().clone();
252-
let pool_key = (Arc::new(domain.to_string()), self.ver);
253-
let fut = RetryableSendRequest {
254-
client,
255-
future: self.send_request(req, pool_key.clone()),
256-
pool_key,
257-
uri,
258-
};
259-
ResponseFuture::new(Box::new(fut))
257+
258+
let mut send_fut = client.send_request(req, pool_key.clone());
259+
future::poll_fn(move || loop {
260+
match send_fut.poll() {
261+
Ok(Async::Ready(resp)) => return Ok(Async::Ready(resp)),
262+
Ok(Async::NotReady) => return Ok(Async::NotReady),
263+
Err(ClientError::Normal(err)) => return Err(err),
264+
Err(ClientError::Canceled {
265+
connection_reused,
266+
mut req,
267+
reason,
268+
}) => {
269+
if !client.retry_canceled_requests || !connection_reused {
270+
// if client disabled, don't retry
271+
// a fresh connection means we definitely can't retry
272+
return Err(reason);
273+
}
274+
275+
trace!("unstarted request canceled, trying again (reason={:?})", reason);
276+
*req.uri_mut() = uri.clone();
277+
send_fut = client.send_request(req, pool_key.clone());
278+
}
279+
}
280+
})
260281
}
261282

262-
//TODO: replace with `impl Future` when stable
263-
fn send_request(&self, mut req: Request<B>, pool_key: PoolKey) -> Box<Future<Item=Response<Body>, Error=ClientError<B>> + Send> {
283+
fn send_request(&self, mut req: Request<B>, pool_key: PoolKey) -> impl Future<Item=Response<Body>, Error=ClientError<B>> {
264284
let race = self.pool_checkout_or_connect(req.uri().clone(), pool_key);
265285

266286
let ver = self.ver;
267287
let executor = self.executor.clone();
268-
Box::new(race.and_then(move |mut pooled| {
288+
race.and_then(move |mut pooled| {
269289
if ver == Ver::Http1 {
270290
// CONNECT always sends origin-form, so check it first...
271291
if req.method() == &Method::CONNECT {
@@ -342,7 +362,7 @@ where C: Connect + Sync + 'static,
342362
}
343363
Ok(res)
344364
}))
345-
}))
365+
})
346366
}
347367

348368
fn pool_checkout_or_connect(&self, uri: Uri, pool_key: PoolKey)
@@ -529,55 +549,6 @@ impl Future for ResponseFuture {
529549
}
530550
}
531551

532-
struct RetryableSendRequest<C, B> {
533-
client: Client<C, B>,
534-
future: Box<Future<Item=Response<Body>, Error=ClientError<B>> + Send>,
535-
pool_key: PoolKey,
536-
uri: Uri,
537-
}
538-
539-
impl<C, B> fmt::Debug for RetryableSendRequest<C, B> {
540-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
541-
f.pad("Future<Response>")
542-
}
543-
}
544-
545-
impl<C, B> Future for RetryableSendRequest<C, B>
546-
where
547-
C: Connect + 'static,
548-
C::Future: 'static,
549-
B: Payload + Send + 'static,
550-
B::Data: Send,
551-
{
552-
type Item = Response<Body>;
553-
type Error = ::Error;
554-
555-
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
556-
loop {
557-
match self.future.poll() {
558-
Ok(Async::Ready(resp)) => return Ok(Async::Ready(resp)),
559-
Ok(Async::NotReady) => return Ok(Async::NotReady),
560-
Err(ClientError::Normal(err)) => return Err(err),
561-
Err(ClientError::Canceled {
562-
connection_reused,
563-
mut req,
564-
reason,
565-
}) => {
566-
if !self.client.retry_canceled_requests || !connection_reused {
567-
// if client disabled, don't retry
568-
// a fresh connection means we definitely can't retry
569-
return Err(reason);
570-
}
571-
572-
trace!("unstarted request canceled, trying again (reason={:?})", reason);
573-
*req.uri_mut() = self.uri.clone();
574-
self.future = self.client.send_request(req, self.pool_key.clone());
575-
}
576-
}
577-
}
578-
}
579-
}
580-
581552
// FIXME: allow() required due to `impl Trait` leaking types to this lint
582553
#[allow(missing_debug_implementations)]
583554
struct PoolClient<B> {
@@ -614,14 +585,14 @@ impl<B> PoolClient<B> {
614585
}
615586

616587
impl<B: Payload + 'static> PoolClient<B> {
617-
fn send_request_retryable(&mut self, req: Request<B>) -> impl_trait!(ty: Future<Item = Response<Body>, Error = (::Error, Option<Request<B>>)> + Send)
588+
fn send_request_retryable(&mut self, req: Request<B>) -> impl Future<Item = Response<Body>, Error = (::Error, Option<Request<B>>)>
618589
where
619590
B: Send,
620591
{
621-
impl_trait!(e: match self.tx {
592+
match self.tx {
622593
PoolTx::Http1(ref mut tx) => Either::A(tx.send_request_retryable(req)),
623594
PoolTx::Http2(ref mut tx) => Either::B(tx.send_request_retryable(req)),
624-
})
595+
}
625596
}
626597
}
627598

0 commit comments

Comments
 (0)