rust 使用sync_db_pools从火箭0.4迁移到火箭0.5:如何返回查询结果同步?

js5cn81o  于 2023-01-26  发布在  其他
关注(0)|答案(1)|浏览(164)

bounty将在5天后过期。回答此问题可获得+100的声誉奖励。Alex正在寻找来自声誉良好来源的答案:试图找到一个简单的™迁移路径:-)

在使用rocket_contrib特性diesel_postgres_pool之前,我尝试将migrate an application从rocket 0.4迁移到rocket 0.5,我认为rocket_sync_db_pools最适合迁移(但我愿意考虑其他选择)
我尝试将代码更改为:

-        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();
+        });

但现在我没有得到实际的结果,但一个承诺。
文档建议使用.await,这似乎会导致调用函数也需要异步,但我不能这样做,因为代码也用于traits,这不容易异步。
我对生 rust 还很陌生,不明白两件(或更多)事情:
1.如果我们在等待结果(使用wait),为什么我的函数必须是异步的?
1.为什么 sync DB池返回异步承诺/需要异步函数。
这是正确的做法吗?
有哪些替代方案可以在不重新构建整个应用程序的情况下修复此问题?

  • 编辑 *

在导入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;

但它似乎给compute的被调用者带来了问题:

identifiers
            .map(|identifier| {
                Self::compute(&conn, identifier.clone()).map(|statistic| (identifier, statistic))
            })
            .collect()

导致错误:

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

EDIT 2:我可能不需要async_trait crate,因为rocket已经提供了这样的解决方案:https://rocket.rs/master/guide/upgrading-from-0.4/#async-traits
编辑3:所以我尝试:

identifiers
            .map(async move |identifier| {
                join_all(Self::compute(&conn, identifier.clone())).await.map(|statistic| (identifier, statistic))
            })
            .collect()

这将导致新错误:-)

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 {`
fwzugrvs

fwzugrvs1#

您可以使用时雄的block_on在非异步函数中解析future

let quality = Handle::current().block_on(async move {
    conn.run( move |conn| {
        subjects::table
            .find(&sub)
            .select(subjects::quality)
            .first::<i16>(conn)
            .ok();
    })
});.

或者,您可以直接使用diesel机箱和r2d2特性进行池化,这不需要使用await。(this is what crates.io does和axum)

相关问题