pub mod impls;
mod streams;
pub mod topology;
pub mod view;
use std::sync::Arc;
use bson::doc;
use mongodb::Client;
use mongodb::options::ClientOptions;
pub use streams::{DEFAULT_STREAM_POOL_SIZE, STREAM_APP_NAME};
pub use topology::Topology;
pub use view::MongoView;
use streams::StreamClient;
#[derive(Clone, Debug)]
pub struct MongoDB {
client: Client,
database: String,
topology: Topology,
view: Option<Arc<MongoView>>,
server_view: bool,
streams: StreamClient,
}
impl MongoDB {
pub fn new(client: Client, database: impl Into<String>) -> Self {
Self::from_parts(client, database.into(), None)
}
fn from_parts(client: Client, database: String, options: Option<ClientOptions>) -> Self {
Self {
client,
database,
topology: Topology::Unknown,
view: None,
server_view: false,
streams: StreamClient::new(options),
}
}
pub async fn connect(uri: &str, database: impl Into<String>) -> vantage_core::Result<Self> {
let connect_error = |e: mongodb::error::Error| {
vantage_core::error!("Failed to connect to MongoDB", details = e.to_string())
};
let options = ClientOptions::parse(uri).await.map_err(connect_error)?;
let client = Client::with_options(options.clone()).map_err(connect_error)?;
let mut mongo = Self::from_parts(client, database.into(), Some(options));
mongo.topology = match mongo.database().run_command(doc! { "hello": 1 }).await {
Ok(reply) => Topology::from_hello(&reply),
Err(_) => Topology::Unknown,
};
Ok(mongo)
}
pub fn topology(&self) -> Topology {
self.topology
}
pub fn supports_change_streams(&self) -> bool {
self.topology.supports_change_streams()
}
#[cfg(feature = "vista")]
pub(crate) fn client(&self) -> &Client {
&self.client
}
pub fn database(&self) -> mongodb::Database {
self.client.database(&self.database)
}
pub fn collection<T: Send + Sync>(&self, name: &str) -> mongodb::Collection<T> {
self.database().collection(name)
}
pub fn doc_collection(&self, name: &str) -> mongodb::Collection<bson::Document> {
self.database().collection(name)
}
}