rust - 包装一个异步函数
问题描述
rust 的 AWS Lambda 运行时要求处理程序类似于async fn handler(event: Value, cx: Context) -> Result<Value, Error>
. 它处理您在内部返回的错误,但我不喜欢它如何记录它们。我想创建一个函数,我可以传递一个处理函数,它返回一个包装版本,它只调用原始版本,检查它的结果,也许是日志,然后返回结果。事实证明,这……很困难。
我已经设法用宏来做到这一点,但我不知道如何让一个真正的功能来做到这一点。任何帮助将非常感激。代码:
use anyhow::{Result};
use lambda_runtime::{handler_fn, Context, Error};
use serde_json::{Value};
// handler
async fn handler(event: Value, cx: Context) -> Result<Value> {
Ok(())
}
// non-generic version (works)
async fn wrapper(event: Value, cx: Context) -> Result<Value> {
let res = handler(event, cx).await;
if let Err(e) = &res {
log::error!("got error from handler: {:?}", &e);
}
res
}
// macro (works)
macro_rules! wrap_handler {
($f:ident) => {{
|e: Value, c: Context| async {
let res = $f(e, c).await;
if let Err(e) = &res {
log::error!("got error from handler: {:?}", &e);
}
res
}
}};
}
// attempt at generic wrapper-creator fn
// should take the function to wrap, and return a Fn wrapping it
use std::future::Future;
use std::pin::Pin;
pub fn make_wrapper<F, FO>(
f: F,
) -> Box<dyn Fn(Value, Context) -> Pin<Box<dyn Future<Output = Result<Value>> + 'static>> + 'static>
where
F: Fn(Value, Context) -> FO + 'static,
FO: Future<Output = Result<Value>> + 'static,
{
use std::sync::Arc;
let af = Arc::new(f);
Box::new(move |v: Value, c: Context| {
let my_f = af.clone();
Box::pin(async move {
//
my_f(v, c).await
})
})
}
// main
#[tokio::main]
async fn main() -> Result<(), Error> {
// use the non-generic version
let func = handler_fn(wrapper);
// OR
// use the macro
let func = handler_fn(wrap_handler!(handler));
// OR
// use the generic wrapper function
let func = handler_fn(make_wrapper(handler));
lambda_runtime::run(func).await?;
Ok(())
}
我最近尝试的错误(上面代码中的 fn )是:
error[E0277]: `dyn Fn(Value, lambda_runtime::Context) -> Pin<Box<(dyn Future<Output = Result<Value, anyhow::Error>> + 'static)>>` cannot be sent between threads safely
--> src/bin/classify-partition.rs:126:25
|
126 | lambda_runtime::run(func).await?;
| ^^^^ `dyn Fn(Value, lambda_runtime::Context) -> Pin<Box<(dyn Future<Output = Result<Value, anyhow::Error>> + 'static)>>` cannot be sent between threads safely
|
::: /home/miles/.cargo/registry/src/github.com-1ecc6299db9ec823/lambda_runtime-0.3.0/src/lib.rs:294:24
|
294 | F: Handler<A, B> + Send + Sync + 'static,
| ---- required by this bound in `run`
|
= help: the trait `Send` is not implemented for `dyn Fn(Value, lambda_runtime::Context) -> Pin<Box<(dyn Future<Output = Result<Value, anyhow::Error>> + 'static)>>`
= note: required because of the requirements on the impl of `Send` for `Unique<dyn Fn(Value, lambda_runtime::Context) -> Pin<Box<(dyn Future<Output = Result<Value, anyhow::Error>> + 'static)>>>`
= note: required because it appears within the type `Box<dyn Fn(Value, lambda_runtime::Context) -> Pin<Box<(dyn Future<Output = Result<Value, anyhow::Error>> + 'static)>>>`
= note: required because it appears within the type `HandlerFn<Box<dyn Fn(Value, lambda_runtime::Context) -> Pin<Box<(dyn Future<Output = Result<Value, anyhow::Error>> + 'static)>>>>`
error[E0277]: `dyn Fn(Value, lambda_runtime::Context) -> Pin<Box<(dyn Future<Output = Result<Value, anyhow::Error>> + 'static)>>` cannot be shared between threads safely
--> src/bin/classify-partition.rs:126:25
|
126 | lambda_runtime::run(func).await?;
| ^^^^ `dyn Fn(Value, lambda_runtime::Context) -> Pin<Box<(dyn Future<Output = Result<Value, anyhow::Error>> + 'static)>>` cannot be shared between threads safely
|
::: /home/miles/.cargo/registry/src/github.com-1ecc6299db9ec823/lambda_runtime-0.3.0/src/lib.rs:294:31
|
294 | F: Handler<A, B> + Send + Sync + 'static,
| ---- required by this bound in `run`
|
= help: the trait `Sync` is not implemented for `dyn Fn(Value, lambda_runtime::Context) -> Pin<Box<(dyn Future<Output = Result<Value, anyhow::Error>> + 'static)>>`
= note: required because of the requirements on the impl of `Sync` for `Unique<dyn Fn(Value, lambda_runtime::Context) -> Pin<Box<(dyn Future<Output = Result<Value, anyhow::Error>> + 'static)>>>`
= note: required because it appears within the type `Box<dyn Fn(Value, lambda_runtime::Context) -> Pin<Box<(dyn Future<Output = Result<Value, anyhow::Error>> + 'static)>>>`
= note: required because it appears within the type `HandlerFn<Box<dyn Fn(Value, lambda_runtime::Context) -> Pin<Box<(dyn Future<Output = Result<Value, anyhow::Error>> + 'static)>>>>`
error[E0277]: `(dyn Future<Output = Result<Value, anyhow::Error>> + 'static)` cannot be sent between threads safely
--> src/bin/classify-partition.rs:126:25
|
126 | lambda_runtime::run(func).await?;
| ^^^^ `(dyn Future<Output = Result<Value, anyhow::Error>> + 'static)` cannot be sent between threads safely
|
= help: the trait `Send` is not implemented for `(dyn Future<Output = Result<Value, anyhow::Error>> + 'static)`
= note: required because of the requirements on the impl of `Send` for `Unique<(dyn Future<Output = Result<Value, anyhow::Error>> + 'static)>`
= note: required because it appears within the type `Box<(dyn Future<Output = Result<Value, anyhow::Error>> + 'static)>`
= note: required because it appears within the type `Pin<Box<(dyn Future<Output = Result<Value, anyhow::Error>> + 'static)>>`
= note: required because of the requirements on the impl of `Handler<Value, Value>` for `HandlerFn<Box<dyn Fn(Value, lambda_runtime::Context) -> Pin<Box<(dyn Future<Output = Result<Value, anyhow::Error>> + 'static)>>>>`
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0277`.
error: could not compile `enrichment-service-functions`
To learn more, run the command again with --verbose.
解决方案
推荐阅读
- php - 如何计算一列的行数并使用 if 条件计算小于 2 行以在 laravel 中运行特定代码
- flutter - 如何在颤动的 alertDialog 中使用 checkboxlisttile?
- batch-file - 我需要打开脚本等待新文件
- asp.net - 如何在asp.net中制作和绑定数据到gridview?
- spring-boot - 如何在测试中创建多个 MockMvc 对象?
- python-3.x - 尝试遍历数据湖中的文件并将它们加载到 SQL Server 中的表中
- python - tensorflow.python.data.ops.dataset_ops.DatasetV1Adapter 是如何工作的?
- python - raspi SerialException:设备报告已准备好读取但未返回任何数据。用于自动遥控车
- angular - 使用模型重置 Angular 表单
- codenameone - Codenameone Android 和 IOS 应用程序未收到来自 Java 服务器的推送通知