fix(examples): Fix tower examples (#624)
Doing
```rust
let clone = self.inner.clone();
Box::pin(async move {
let response = clone.call(request).await?;
Ok(response)
})
```
If `self.inner` is (or contains) a `tower::buffer::Buffer` might panic.
That is because cloning a `Buffer` drops the permit that was acquired in
`poll_ready`, meaning it is no longer ready and panic in `call`.
The solution is to use `mem::replace` to take the ready service and pass
that into the async block.
Fixes https://github.com/hyperium/tonic/issues/545
This commit is contained in:
@@ -56,12 +56,17 @@ mod service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self, req: Request<BoxBody>) -> Self::Future {
|
fn call(&mut self, req: Request<BoxBody>) -> Self::Future {
|
||||||
let mut channel = self.inner.clone();
|
// This is necessary because tonic internally uses `tower::buffer::Buffer`.
|
||||||
|
// See https://github.com/tower-rs/tower/issues/547#issuecomment-767629149
|
||||||
|
// for details on why this is necessary
|
||||||
|
let clone = self.inner.clone();
|
||||||
|
let mut inner = std::mem::replace(&mut self.inner, clone);
|
||||||
|
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
// Do extra async work here...
|
// Do extra async work here...
|
||||||
|
let response = inner.call(req).await?;
|
||||||
|
|
||||||
channel.call(req).await.map_err(Into::into)
|
Ok(response)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,12 +71,17 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self, req: HyperRequest<Body>) -> Self::Future {
|
fn call(&mut self, req: HyperRequest<Body>) -> Self::Future {
|
||||||
let mut svc = self.inner.clone();
|
// This is necessary because tonic internally uses `tower::buffer::Buffer`.
|
||||||
|
// See https://github.com/tower-rs/tower/issues/547#issuecomment-767629149
|
||||||
|
// for details on why this is necessary
|
||||||
|
let clone = self.inner.clone();
|
||||||
|
let mut inner = std::mem::replace(&mut self.inner, clone);
|
||||||
|
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
// Do async work here....
|
// Do extra async work here...
|
||||||
|
let response = inner.call(req).await?;
|
||||||
|
|
||||||
svc.call(req).await
|
Ok(response)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user