与lazy_static 一起使用'await' 的替代方法!生锈的宏? [英] alternative to using 'await' with lazy_static! macro in rust?

查看:72
本文介绍了与lazy_static 一起使用'await' 的替代方法!生锈的宏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在项目中使用异步 MongoDB.

I wanted to use Async MongoDB in a project.

不想绕过客户端,因为它需要绕过多个任务和线程.所以我使用惰性静态保留了一个静态客户端.但是我不能在初始化块中使用 await.

Didn't want to pass around the client because it would need to go around multiple tasks and threads. So I kept a static client using lazy static. However I can't use await in the initialization block.

我可以做些什么来解决这个问题?

What can I do to work around this?

也欢迎提出在没有 lazy_static 的情况下完全不同的建议.

Suggestions for doing it completely differently without lazy_static is also welcome.

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 论坛中某人的建议采用了这种方法.

I went with this approach based on someone's suggestion in rust forums.

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

这篇关于与lazy_static 一起使用'await' 的替代方法!生锈的宏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆