use crate::error::Error;
use async_trait::async_trait;
use bb8::ManageConnection;
use mongodb::{bson::doc, options::ClientOptions, Client, Database};
#[derive(Clone, Debug)]
pub struct Mongodb {
client_options: ClientOptions,
db_name: String,
}
impl Mongodb {
pub fn new<T>(client_options: ClientOptions, db_name: T) -> Mongodb
where
T: Into<String>,
{
Mongodb {
client_options,
db_name: db_name.into(),
}
}
}
#[async_trait]
impl ManageConnection for Mongodb {
type Connection = Database;
type Error = Error;
async fn connect(&self) -> Result<Self::Connection, Self::Error> {
let client = Client::with_options(self.client_options.clone())?;
Ok(client.database(&self.db_name))
}
async fn is_valid(&self, conn: &mut Self::Connection) -> Result<(), Self::Error> {
let _doc = conn.run_command(doc! { "ping": 1 }, None).await?;
Ok(())
}
fn has_broken(&self, _conn: &mut Self::Connection) -> bool {
false
}
}
#[cfg(test)]
mod test {
use super::Mongodb;
use anyhow::Result;
use bb8::Pool;
use mongodb::{
bson::doc,
options::{ClientOptions, Credential},
};
use std::env;
#[tokio::test]
async fn new_works() -> Result<()> {
let mut client_options = ClientOptions::parse(env::var("BB8_MONGODB_URL")?).await?;
client_options.credential = Some(
Credential::builder()
.username(env::var("BB8_MONGODB_USER").ok())
.password(env::var("BB8_MONGODB_PASSWORD").ok())
.build(),
);
let connection_manager = Mongodb::new(client_options, "admin");
let pool = Pool::builder().build(connection_manager).await?;
let conn = pool.get().await?;
assert_eq!(conn.name(), "admin");
let doc = conn.run_command(doc! { "ping": 1 }, None).await?;
assert_eq!(doc! { "ok": 1 }, doc);
Ok(())
}
}