我正在嘗試使用 lambda_http 但遇到問題。
基本上,我試圖通過將一個服務特征實作的物件傳遞給它來創建一個 service_fn,以獲取一個保存狀態的結構。但它似乎在 std::marker::Send 上絆倒了
struct Handler {
db: aws_sdk_dynamodb::Client,
s3: aws_sdk_s3::Client,
}
impl Handler {
..some_stuff..
}
pub trait Service {
fn route<T>(&self, data: T) -> serde_json::Value;
}
impl Service for Handler {
fn route<Request>(&self, req: Request) -> serde_json::Value {
json!({ "error": "Route not found" })
}
}
pub async fn run(service: Arc<impl Service>) -> Result<(), Error> {
let func = service_fn(|req| lambda_handler(req, service.clone()));
lambda_http::run(func).await?;
Ok(())
}
pub(crate) async fn lambda_handler(
evt: Request,
svc: Arc<impl Service>,
) -> Result<impl IntoResponse, Error> {
let reply = svc.route(evt);
let response = LambdaResponse::builder().(..some_stuff..).body(reply.to_string()).unwrap();
Ok(response)
}
由于某種原因,這并不完全有效,它與同步有關,但不知道如何修復它。
Compiling runtime v0.1.0 (/home/xyz/Documents/lservice/runtime)
warning: unused import: `serde_json::json`
--> runtime/src/lib.rs:12:5
|
12 | use serde_json::json;
| ^^^^^^^^^^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
error: future cannot be sent between threads safely
--> runtime/src/lib.rs:21:22
|
21 | lambda_http::run(func).await?;
| ^^^^ future returned by `lambda_handler` is not `Send`
|
note: captured value is not `Send`
--> runtime/src/lib.rs:29:5
|
29 | svc: Arc<impl Service>,
| ^^^ has type `Arc<impl Service>` which is not `Send`
note: required by a bound in `lambda_http::run`
--> /home/xyz/.cargo/registry/src/github.com-1ecc6299db9ec823/lambda_http-0.7.1/src/lib.rs:185:16
|
185 | S::Future: Send 'a,
| ^^^^ required by this bound in `lambda_http::run`
help: consider further restricting this bound
|
19 | pub async fn run(service: Arc<impl Service std::marker::Sync>) -> Result<(), Error> {
|
error: future cannot be sent between threads safely
--> runtime/src/lib.rs:21:22
|
21 | lambda_http::run(func).await?;
| ^^^^ future returned by `lambda_handler` is not `Send`
|
note: captured value is not `Send`
--> runtime/src/lib.rs:29:5
|
29 | svc: Arc<impl Service>,
| ^^^ has type `Arc<impl Service>` which is not `Send`
note: required by a bound in `lambda_http::run`
--> /home/xyz/.cargo/registry/src/github.com-1ecc6299db9ec823/lambda_http-0.7.1/src/lib.rs:185:16
|
185 | S::Future: Send 'a,
| ^^^^ required by this bound in `lambda_http::run`
help: consider further restricting this bound
|
19 | pub async fn run(service: Arc<impl Service std::marker::Send>) -> Result<(), Error> {
|
warning: `runtime` (lib) generated 1 warning
error: could not compile `runtime` due to 2 previous errors; 1 warning emitted
但是,如果我只是將 dynamodb.clone() 直接傳遞給它而不是嵌套在 Handler 結構中,這確實有效,所以我知道它可能需要我在 Handler 上實作 Send,但不確定我是否在正確的軌道上所以需要在前進的道路上有一點幫助。
<#更新#>
使這最終起作用的一件事是僅使用 Arc<Mutex> 保護處理程式。由于它抱怨一個值無法在執行緒之間安全傳遞,我只是在發送它之前鎖定它。雖然我無法擺脫這是一種大錘方法的感覺,特別是考慮到如果我使用 lambda_runtime::run(而不是 lambda_http::run),這似乎只適用于一個簡單的 Arc::clone()。
<#更新 2 #>
@Mikdore 提出的將 Sync 實作為超級特征的建議起到了作用。現在它不需要任何外部鎖,就可以正常作業了。
uj5u.com熱心網友回復:
您不必實施Send. 而且您幾乎總是不應該這樣做。如果你的 struct 的所有成員都是Send,rust 會自動為你實作它。編譯器會告訴您問題所在:
help: consider further restricting this bound
|
19 | pub async fn run(service: Arc<impl Service std::marker::Send>) -> Result<(), Error> {
|
理論上任何任意型別都可以實作Service。并非所有這些型別都是Send. 正如編譯器告訴您的那樣,您可以將函式限制為Arc<impl Service Send>. 但是,也許更明智的是,您還可以通過以下方式制作 ,Service的超特征Send:
trait Service: Send {
//...
}
這樣,每個型別的實作Service都需要實作Send,并且您可以impl Service在異步背景關系中使用。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/529527.html
