I am trying to migrate an application from rocket 0.4 to rocket 0.5 Before it was using rocket_contrib feature diesel_postgres_pool and I though rocket_sync_db_pools would be the best fit for migration (but I am open to alternatives here)
I tried to change the code like this:
- let quality = subjects::table
- .find(&sub)
- .select(subjects::quality)
- .first::<i16>(&conn.0)
- .ok();
+ let quality = conn.run( move |conn| {
+ subjects::table
+ .find(&sub)
+ .select(subjects::quality)
+ .first::<i16>(conn)
+ .ok();
+ });
But now I am not getting the actual result but a Promise.
The documentation suggests to use .await which seems to cause that the calling func needs to be async, too. But I cannot do this, because the code is also used in traits, which cannot be async easily.
I am pretty new to rust and don't understand two (or more) things:
Is this the right approach?
What are the alternatives to fix this without rebuilding the full application?
EDIT
This is a step forward, after importing async_trait.
#[async_trait]
impl Statistic for Subject {
async fn compute(conn: &DbConn, sub: String) -> Result<Self, Error> {
[...]
let quality = conn.run( move |conn| {
return subjects::table
.find(&sub)
.select(subjects::quality)
.first::<i16>(conn)
.ok();
}).await;
But it seems to bring problems on the callee of compute:
identifiers
.map(|identifier| {
Self::compute(&conn, identifier.clone()).map(|statistic| (identifier, statistic))
})
.collect()
Causes an error:
23 | Self::compute(&conn, identifier.clone()).map(|statistic| (identifier, statistic))
| ^^^ `Pin<Box<dyn std::future::Future<Output = Result<Self, error::Error>> + std::marker::Send>>` is not an iterator
EDIT2: I might not need the async_trait crate, as rocket already supplies such a solution: https://rocket.rs/master/guide/upgrading-from-0.4/#async-traits
EDIT3: So I tried:
identifiers
.map(async move |identifier| {
join_all(Self::compute(&conn, identifier.clone())).await.map(|statistic| (identifier, statistic))
})
.collect()
This leads to a new error :-)
error[E0658]: async closures are unstable
--> src/aggregator.rs:23:18
|
23 | .map(async move |identifier| {
| ^^^^^
|
= note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
= help: to use an async block, remove the `||`: `async {`
EDIT4:
After trying pigeonhands answer with this code:
let quality = Handle::current().block_on(async move {
conn.run(move |conn| {
subjects::table
.find(&sub)
.select(subjects::quality)
.first::<i16>(conn)
.ok();
})
});
Ok(Subject {
sub,
quality,
count,
opinion_count,
positive_count,
confirmed_count,
})
I am getting
error[E0308]: mismatched types
--> src/aggregator.rs:84:13
|
74 | conn.run(move |conn| {
| ----------- the found closure
...
84 | quality,
| ^^^^^^^ expected enum `std::option::Option`, found opaque type
You could use tokio's block_on to resolve the future in a non-async function
let quality = Handle::current().block_on(async move {
conn.run( move |conn| {
subjects::table
.find(&sub)
.select(subjects::quality)
.first::<i16>(conn)
.ok()
}).await
});.
Or you could use the diesel crate directly with the r2d2 feature for pooling, witch does not require using await. (this is what crates.io does with axum)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With