gpt4 book ai didi

asynchronous - Rust lazy_static 与 async/await?

转载 作者:行者123 更新时间:2023-12-04 03:25:39 24 4
gpt4 key购买 nike

我是 Rust 的新手。我正在将 mongodb 与异步运行时(tokio)一起使用。
我想全局初始化 mongo 客户端,所以我使用了一个名为 lazy_static 的 crate .问题是mongodb是异步连接的,现在lazy_static不支持async关键词...

use mongodb::Client;
async {
let client = Client::with_uri_str(&env_var("MONGO_URL")).await.unwrap();
}
那么我如何初始化 client全局对象?
有关的:
Async/await support?

alternative to using 'await' with lazy_static! macro in rust?

最佳答案

如果您使用新的运行时并且首先在现有运行时的上下文中使用惰性静态,如下例所示:

use lazy_static::lazy_static;
use mongodb::Client;

lazy_static! {
static ref CLIENT: Client = {
tokio::runtime::Runtime::new().unwrap().block_on(async {
let uri = std::env::var("MONGO_URL").unwrap();
let client = Client::with_uri_str(&uri).await.unwrap();

client
})
};
}

#[tokio::main]
async fn main() {
let _db = CLIENT.database("local");
}
你会得到提到的错误:
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.', C:\Users\kmdreko\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-1.6.1\src\runtime\enter.rs:39:9
您可以通过使用不同的运行时( futures vs tokio vs async-std )来规避这一点,但这并不理想,因为它仍然会阻止底层运行。

解决这个问题的一个相对直接的方法是不要尝试懒惰地去做并立即在 main 中初始化它。 .这样你就可以直接使用异步运行时而不必担心在其他地方需要一个:
use mongodb::Client;
use once_cell::sync::OnceCell;

static CLIENT: OnceCell<Client> = OnceCell::new();

#[tokio::main]
async fn main() {
let uri = std::env::var("MONGO_URL").unwrap();
let client = Client::with_uri_str(&uri).await.unwrap();
CLIENT.set(client).unwrap();

let _db = CLIENT.get().unwrap().database("local");
}
这可以通过 OnceCell 完成(如上所示)或类似 RwLock 的东西如有必要。

对于您要实现的目标,最直接的答案是使用 async_once crate,这使它使用接收器的运行时来驱动异步函数。
use async_once::AsyncOnce;
use lazy_static::lazy_static;
use mongodb::Client;

lazy_static! {
static ref CLIENT: AsyncOnce<Client> = AsyncOnce::new(async {
let uri = std::env::var("MONGO_URL").unwrap();
let client = Client::with_uri_str(&uri).await.unwrap();

client
});
}

#[tokio::main]
async fn main() {
let _db = CLIENT.get().await.database("local");
}
这假设客户端的所有或几乎所有使用都在异步上下文中。

关于asynchronous - Rust lazy_static 与 async/await?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67650879/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com