是否有可能在Rust Diesel交易中运行一个PECC函数

8iwquhpp  于 2023-10-20  发布在  其他
关注(0)|答案(2)|浏览(146)

我正在使用rust diesel transaction来执行一些tasc任务,现在我尝试使用这样的新时雄运行时(这只是一个最小的演示来展示问题):

use diesel::result::Error;
use diesel::Connection;
use rust_wheel::config::db::config;
use tokio::runtime::Runtime;

#[tokio::main]
async fn main() {
    let mut connection = config::connection("TEX_DATABASE_URL".to_string());
    let _trans_result: Result<(), Error> = connection.transaction(|_connection| {
        let rt = Runtime::new().unwrap();
        Ok(rt.block_on(async { do_create_proj_trans().await }))
    });
}

async fn do_create_proj_trans() {
    println!("doing...")
}

这段代码显示了这样的错误:

thread 'main' panicked at 'Cannot start a runtime from within a runtime. This happens because a function (like `block_on`) attempted to block the current thread while the thread is being used to drive asynchronous tasks.', /Users/xiaoqiangjiang/.cargo/registry/src/mirrors.tuna.tsinghua.edu.cn-df7c3c540f42cdbd/tokio-1.32.0/src/runtime/scheduler/multi_thread/mod.rs:86:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

当我删除运行时,显示这样的错误:

`await` is only allowed inside `async` functions and blocks
only allowed inside `async` functions and blocks

在生 rust 的柴油transactio块中是否可以运行一个aprc功能?这是货物。

[package]
name = "rust-learn"
version = "0.1.0"
edition = "2018"

[dependencies]
tokio = { version = "1.17.0", features = ["full"] }
serde = { version = "1.0.64", features = ["derive"] }
serde_json = "1.0.64"
futures = "0.3"
tokio-stream = "0.1"
rust_wheel = { git = "https://github.com/jiangxiaoqiang/rust_wheel.git", branch = "diesel2.0" }
log4rs = "1.2.0"
log = "0.4.0"
diesel = { version = "2.1.0", features = ["postgres","64-column-tables","chrono","serde_json"] }
zynd9foi

zynd9foi1#

是的,这是可能的,但是你试图在一个用于驱动任务的线程中完成它,你不应该这样做。相反,在一个线程上的任务中执行它,在这个线程上可以使用task::spawn_blocking阻塞:

#[tokio::main]
async fn main() {
    let _trans_result: Result<(), Error> = tokio::task::spawn_blocking(|| {
        let mut connection = config::connection("TEX_DATABASE_URL".to_string());
        connection.transaction(|_connection| {
            let rt = tokio::runtime::Handle::current();
            Ok(rt.block_on(async { do_create_proj_trans().await }))
        })
    }).await.unwrap();
}

我还选择使用当前运行时,而不是创建一个不同的运行时。

zzwlnbp8

zzwlnbp82#

作为替代方案,有diesel-async crate可以使整个事务async

[dependencies]
diesel = { version = "2.1.1", features = ["postgres"] }
diesel-async = { version = "0.4.1", features = ["postgres"] }
tokio = { version = "1.32.0", features = ["macros", "rt-multi-thread"] }
use diesel::result::Error;
use diesel_async::pg::AsyncPgConnection;
use diesel_async::AsyncConnection;

fn connection(_: String) -> AsyncPgConnection { unimplemented!() }

#[tokio::main]
async fn main() {
    let mut conn = connection("TEX_DATABASE_URL".to_string());
    let _result: Result<(), Error> = conn.transaction(|_conn| Box::pin(async {
        // do database stuff
        do_create_proj_trans().await;
        // do database stuff
        Ok(())
    })).await;
}

async fn do_create_proj_trans() {
    println!("doing...")
}

相关问题