适用于 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.