【发布时间】:2021-03-04 20:42:03
【问题描述】:
我正在尝试服用补品routeguide tutorial,并将客户端变成rocket 服务器。我只是接受响应并将 gRPC 转换为字符串。
service RouteGuide {
rpc GetFeature(Point) returns (Feature) {}
rpc ListFeatures(Rectangle) returns (stream Feature) {}
}
这对于 GetFeature 来说已经足够好了。对于 ListFeatures 查询,就像 Tonic 允许客户端在响应中使用流一样,我想将其传递给 Rocket 客户端。我看到 Rocket 支持 streaming 响应,但我需要实现 AsyncRead 特征。
有没有办法做这样的事情?以下是关于我正在做的事情的精简版:
struct FeatureStream {
stream: tonic::Streaming<Feature>,
}
impl AsyncRead for FeatureStream {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf<'_>,
) -> Poll<std::io::Result<()>> {
// Write out as utf8 any response messages.
match Pin::new(&mut self.stream.message()).poll(cx) {
Poll::Pending => Poll::Pending,
Poll::Ready(feature) => Poll::Pending,
}
}
}
#[get("/list_features")]
async fn list_features(client: State<'_, RouteGuideClient<Channel>>) -> Stream<FeatureStream> {
let rectangle = Rectangle {
low: Some(Point {
latitude: 400_000_000,
longitude: -750_000_000,
}),
high: Some(Point {
latitude: 420_000_000,
longitude: -730_000_000,
}),
};
let mut client = client.inner().clone();
let stream = client
.list_features(Request::new(rectangle))
.await
.unwrap()
.into_inner();
Stream::from(FeatureStream { stream })
}
#[rocket::launch]
async fn rocket() -> rocket::Rocket {
rocket::ignite()
.manage(
create_route_guide_client("http://[::1]:10000")
.await
.unwrap(),
)
.mount("/", rocket::routes![list_features,])
}
出现错误:
error[E0277]: `from_generator::GenFuture<[static generator@Streaming<Feature>::message::{closure#0} for<'r, 's, 't0, 't1, 't2> {ResumeTy, &'r mut Streaming<Feature>, [closure@Streaming<Feature>::message::{closure#0}::{closure#0}], rocket::futures::future::PollFn<[closure@Streaming<Feature>::message::{closure#0}::{closure#0}]>, ()}]>` cannot be unpinned
--> src/web_user.rs:34:15
|
34 | match Pin::new(&mut self.stream.message()).poll(cx) {
| ^^^^^^^^ within `impl std::future::Future`, the trait `Unpin` is not implemented for `from_generator::GenFuture<[static generator@Streaming<Feature>::message::{closure#0} for<'r, 's, 't0, 't1, 't2> {ResumeTy, &'r mut Streaming<Feature>, [closure@Streaming<Feature>::message::{closure#0}::{closure#0}], rocket::futures::future::PollFn<[closure@Streaming<Feature>::message::{closure#0}::{closure#0}]>, ()}]>`
|
::: /home/matan/.cargo/registry/src/github.com-1ecc6299db9ec823/tonic-0.4.0/src/codec/decode.rs:106:40
|
106 | pub async fn message(&mut self) -> Result<Option<T>, Status> {
| ------------------------- within this `impl std::future::Future`
|
= note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `impl std::future::Future`
= note: required by `Pin::<P>::new`
【问题讨论】:
-
看起来
message()函数是从 tonic Streaming 中选择下一条消息的助手。你不需要message()函数来为AsyncRead选择下一条消息你已经有Stream,你可以自己选择下一条消息,这里是代码play.rust-lang.org/…(它返回Pending对于所有情况正如您的代码所做的那样,您可以根据需要更改它)
标签: rust async-await rust-tokio rust-rocket