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 {
|
||||
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 {
|
||||
// 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 {
|
||||
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 {
|
||||
// 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