mongodb - 替代使用带有lazy_static的'await'!生锈的宏?
问题描述
我想在一个项目中使用 Async MongoDB。
不想绕过客户端,因为它需要绕过多个任务和线程。所以我使用惰性静态保持了一个静态客户端。但是我不能在初始化块中使用 await 。
我能做些什么来解决这个问题?
也欢迎提出在没有lazy_static 的情况下完全不同的建议。
use std::env;
use futures::stream::StreamExt;
use mongodb::{
bson::{doc, Bson},
options::ClientOptions,
Client,
};
lazy_static! {
static ref MONGO: Option<Client> = {
if let Ok(token) = env::var("MONGO_AUTH") {
if let Ok(client_options) = ClientOptions::parse(&token).await
^^^^^
{
if let Ok(client) = Client::with_options(client_options) {
return Some(client);
}
}
}
return None;
};
}
解决方案
我根据 rust 论坛中某人的建议采用了这种方法。
static MONGO: OnceCell<Client> = OnceCell::new();
static MONGO_INITIALIZED: OnceCell<tokio::sync::Mutex<bool>> = OnceCell::new();
pub async fn get_mongo() -> Option<&'static Client> {
// this is racy, but that's OK: it's just a fast case
let client_option = MONGO.get();
if let Some(_) = client_option {
return client_option;
}
// it hasn't been initialized yet, so let's grab the lock & try to
// initialize it
let initializing_mutex = MONGO_INITIALIZED.get_or_init(|| tokio::sync::Mutex::new(false));
// this will wait if another task is currently initializing the client
let mut initialized = initializing_mutex.lock().await;
// if initialized is true, then someone else initialized it while we waited,
// and we can just skip this part.
if !*initialized {
// no one else has initialized it yet, so
if let Ok(token) = env::var("MONGO_AUTH") {
if let Ok(client_options) = ClientOptions::parse(&token).await {
if let Ok(client) = Client::with_options(client_options) {
if let Ok(_) = MONGO.set(client) {
*initialized = true;
}
}
}
}
}
drop(initialized);
MONGO.get()
}
推荐阅读
- typo3-9.x - 如何创建动态使用 expr() 的约束?
- php - 如何使用构造函数将角色添加到组
- java - Java StampedLock:当有人阅读时作家会发生什么
- angular - 如何设置每 25ms 的计时器?
- ggplot2 - 条形图上堆积在错误位置的误差线
- node.js - 我需要在渲染之前在服务器端读取一个 cookie
- python-3.x - 如何在 wxPython 中以编程方式扩展 PyCollapsiblePane?
- python - 连接python和mysql数据库时出现错误
- sql - 带有 sum 的子查询返回 null
- c# - Asp.net 核心:创建 ILogger 的新实例
每个请求成本昂贵?