Client我想全局初始化 MongoDB,所以我使用了惰性静态箱。问题是客户端是异步连接的,lazy_static!不支持async关键字:
use mongodb::Client;
async {
let client = Client::with_uri_str(&env_var("MONGO_URL")).await.unwrap();
}
Run Code Online (Sandbox Code Playgroud)
那么我该如何初始化呢client?
有关的:
kmd*_*eko 29
如果您使用新的运行时,并且首先在现有运行时的上下文中使用惰性静态,如下例所示:
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");
}
Run Code Online (Sandbox Code Playgroud)
您将收到提到的错误:
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");
}
Run Code Online (Sandbox Code Playgroud)
您可以通过使用不同的运行时(futuresvs tokiovs 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");
}
Run Code Online (Sandbox Code Playgroud)
如果需要的话,可以通过OnceCell(如上所示)或类似的方式来完成。更新:现在也在标准库中做同样的事情。RwLockOnceLock
对于您想要实现的目标,最直接的答案是使用async_once板条箱,这使得它使用接收器的运行时来驱动异步函数。
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");
}
Run Code Online (Sandbox Code Playgroud)
这假设客户端的所有或几乎所有使用都将在异步上下文中。
或者您可以使用OnceCellfrom tokio,它类似于OnceCell/ ,OnceLock但它的初始化程序async类似于AsyncOnce这样您可以在辅助函数中main或通过辅助函数单独初始化它:
use mongodb::Client;
use tokio::sync::OnceCell;
static CLIENT: OnceCell<Client> = OnceCell::const_new();
async fn get_client() -> &'static Client {
CLIENT.get_or_init(|| async {
let uri = std::env::var("MONGO_URL").unwrap();
let client = Client::with_uri_str(&uri).await.unwrap();
client
})
.await
}
#[tokio::main]
async fn main() {
let _db = get_client().await.database("local");
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7271 次 |
| 最近记录: |