如何读取MongoDB集群的哪个主机回答了我的查询(在Rust中)?

polhcujo  于 2023-10-16  发布在  Go
关注(0)|答案(1)|浏览(100)

我在Rust应用程序中使用MongoDB。我想知道集群中的哪个服务器发送查询的响应。
当我使用tracing crate事件时,我可以看到信息(serverHost=),但我想在我的应用程序中使用它,不知道如何访问它。
我想,我需要的是ServerInfo.address,但它不能从我的客户端示例访问。

编辑:下面的代码是我尝试做的最小值。如何将响应服务器的主机名分配给address变量?

use mongodb::{bson::doc, options::{ClientOptions, ServerApi, ServerApiVersion}, Client};

#[tokio::main]
async fn main() -> mongodb::error::Result<()> {
    // Replace the placeholder with your MongoDB connection string
    let uri = "<connection string>";
    let mut client_options = ClientOptions::parse(uri).await?;
    let client = Client::with_options(client_options)?;
    
    // Send a ping to confirm a successful connection
    client
        .database("admin")
        .run_command(doc! {"ping": 1}, None)
        .await?;
    
    // Somehow get hostname of responding server
    // let address = ...? 

    println!("Got ping from {}", address);

    Ok(())
}
xxhby3vn

xxhby3vn1#

您可以定义一个CommandEventHandler,以便在构建Client时使用。它将在命令启动、成功或失败时接收回调。每个回调负载都包含具有MongoDB服务器地址的ConnectionInfo
如果你只是聚合指标,那么这可能就是你所需要的。但是,如果您实际上需要更新或查询的 * 调用者 * 知道使用了什么地址,那么就有点麻烦了。我建议使用task-local(如果使用Client)或thread-local(如果使用sync Client),事件处理程序可以将地址存储到调用者可以从中提取的地址中。
下面是我使用task-locals得到的结果:

use std::sync::{Arc, OnceLock};

use mongodb::bson::doc;
use mongodb::event::command::{CommandEventHandler, CommandSucceededEvent};
use mongodb::options::{ClientOptions, ServerAddress};
use mongodb::Client;
use tokio::task_local;

task_local! {
    static SERVER_ADDRESS: OnceLock<ServerAddress>;
}

struct ServerAddressHandler;

impl CommandEventHandler for ServerAddressHandler {
    fn handle_command_succeeded_event(&self, event: CommandSucceededEvent) {
        let _ = SERVER_ADDRESS.with(|address| address.set(event.connection.address));
    }
}

#[tokio::main]
async fn main() -> mongodb::error::Result<()> {
    let uri = "mongodb://localhost:27017";

    let mut client_options = ClientOptions::parse(uri).await?;
    client_options.command_event_handler = Some(Arc::new(ServerAddressHandler));
    let client = Client::with_options(client_options)?;

    SERVER_ADDRESS
        .scope(OnceLock::new(), async {
            let result = client
                .database("admin")
                .run_command(doc! {"ping": 1}, None)
                .await;

            let address = SERVER_ADDRESS.with(|address| address.get().cloned());
            if let Some(address) = address {
                println!("Got ping from {address}");
            }

            result
        })
        .await?;

    Ok(())
}
Got ping from localhost:27017

相关问题