使用async block和ServiceFn实现tower::Layer



我试图实现一个塔层使用塔::layer_fn和塔::service_fn助手函数像这样(编译好):

use std::convert::Infallible;
use tower::Service;
use tower::util::ServiceFn;

tower::ServiceBuilder::new()
.layer_fn(|mut service: ServiceFn<_>| {
// Just do nothing except calling the downstream service
tower::service_fn(move |request| {
service.call(request)
})
})
.service_fn(|request: String| {
// Echo service
async move {
let response = request;
Ok::<_, Infallible>(response)
}
});

因为我在实际代码中有多个.await点,我想避免手工实现Layer,即Service::call(),而是在async块中这样做。对于echo服务,这确实工作得很好,如上所示。但是,对于layer_fn中的服务,这不会编译:

tower::ServiceBuilder::new()
.layer_fn(|mut service: ServiceFn<_>| {
tower::service_fn(move |request| {
// Just do nothing except calling the downstream service
async move {
let response: Result<String, Infallible> = service.call(request).await;
// Do something with response, await'ing thereby
response
}
})
})
.service_fn(|request: String| {
// Echo service
async move {
let response = request;
Ok::<_, Infallible>(response)
}
});
});

我得到以下错误,但我不知道如何帮助编译器键入:

error[E0698]: type inside `async` block must be known in this context
--> src/main.rs:32:64
|
32 |                     let response: Result<String, Infallible> = service.call(request).await;
|                                                                ^^^^^^^ cannot infer type
|
note: the type is part of the `async` block because of this `await`
--> src/main.rs:32:85
|
32 |                     let response: Result<String, Infallible> = service.call(request).await;
|                                                                                     ^^^^^^

异步上下文中的类型推断有时不如同步上下文中强大。不幸的是,我能看到的唯一解决方案是使用夜间type_alias_impl_trait:

#![feature(type_alias_impl_trait)]
type Fut = impl Future<Output = Result<String, Infallible>>;
type Callback = impl Fn(String) -> Fut;
tower::ServiceBuilder::new()
.layer_fn(|mut service: ServiceFn<Callback>| {
tower::service_fn(move |request| {
// Just do nothing except calling the downstream service
async move {
let response: Result<String, Infallible> = service.call(request).await;
// Do something with response, await'ing thereby
response
}
})
})
.service_fn::<Callback>(|request: String| {
// Echo service
async move {
let response = request;
Ok::<_, Infallible>(response)
}
});

或者将回调和future都装箱:

type Fut = Pin<Box<dyn Future<Output = Result<String, Infallible>>>>;
type Callback = Box<dyn Fn(String) -> Fut>;
tower::ServiceBuilder::new()
.layer_fn(|mut service: ServiceFn<Callback>| {
tower::service_fn(move |request| {
// Just do nothing except calling the downstream service
async move {
let response: Result<String, Infallible> = service.call(request).await;
// Do something with response, await'ing thereby
response
}
})
})
.service_fn::<Callback>(Box::new(|request: String| {
// Echo service
Box::pin(async move {
let response = request;
Ok::<_, Infallible>(response)
})
}));

相关内容

  • 没有找到相关文章

最新更新