tuxmain
1
Hello, I don't understand why cloning a variable works in a regular closure, but not in an async closure:
let route_get_mix_confirm = warp::path("get-mix-confirm")
.and(warp::post())
.and(warp::body::bytes())
.and(warp::body::content_length_limit(REQUEST_MAX_SIZE))
.map({
let dbs = dbs.clone();
let indexes = indexes.clone();
move |raw: Bytes| {
bincode::serialize(&serve_get_mix_confirm(dbs.clone(), indexes.clone(), raw))
.unwrap()
}
});
let route_get_mix_confirm_blocking = warp::path("get-mix-confirm-blocking")
.and(warp::post())
.and(warp::body::bytes())
.and(warp::body::content_length_limit(REQUEST_MAX_SIZE))
.map({
let dbs = dbs.clone();
let indexes = indexes.clone();
async move |raw: Bytes| {
bincode::serialize(&serve_get_mix_confirm_blocking(dbs.clone(), indexes.clone(), raw).await)
.unwrap()
}
});
The async version makes an error: closure is `FnOnce` because it moves the variable `dbs` out of its environment.
Why this, and how to makes it work?
1 Like
alice
2
I see that you are using the unstable async closure feature. I would avoid that. Instead use an ordinary closure, that:
- first clones
dbs
- Then moves the clone into an async block.
- Returns the async block.
1 Like
tuxmain
3
With your solution this part makes no more error, but warp::serve is unhappy:
let route_get_mix_confirm_blocking = warp::path("get-mix-confirm-blocking")
.and(warp::post())
.and(warp::body::bytes())
.and(warp::body::content_length_limit(REQUEST_MAX_SIZE))
.map({
let dbs = dbs.clone();
let indexes = indexes.clone();
move |raw: Bytes| {
let dbs = dbs.clone();
let indexes = indexes.clone();
async move {
bincode::serialize(&serve_get_mix_confirm_blocking(dbs, indexes, raw).await)
.unwrap()
}
}
});
warp::serve(route_get_mix_confirm_blocking).run(config.listen).await;
// Error: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Reply` is not implemented for `impl Future`
alice
4
I'm pretty sure you need to call something else than map when it is async, but I don't know what the right one is. Maybe then?
1 Like
tuxmain
5
Thank you, it works!
let route_get_mix_confirm_blocking = warp::path("get-mix-confirm-blocking")
.and(warp::post())
.and(warp::body::bytes())
.and(warp::body::content_length_limit(REQUEST_MAX_SIZE))
.and_then({
let dbs = dbs.clone();
let indexes = indexes.clone();
move |raw: Bytes| {
let dbs = dbs.clone();
let indexes = indexes.clone();
async move {
Result::<Vec<u8>, std::convert::Infallible>::Ok(
bincode::serialize(
&serve_get_mix_confirm_blocking(dbs, indexes, raw).await,
)
.unwrap(),
)
}
}
});
I think this should be in the example, for people unfamiliar with async...
2 Likes
alice
6
You can always open a PR to add it 
1 Like
system
Closed
7
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.