use std::sync::Arc;
#[cfg(feature = "vista")]
use bson::Document;
use mongodb::Client;
use mongodb::options::ClientOptions;
use tokio::sync::OnceCell;
#[cfg(feature = "vista")]
use vantage_core::{Result, error};
use super::MongoDB;
pub const DEFAULT_STREAM_POOL_SIZE: u32 = 100;
pub const STREAM_APP_NAME: &str = "vantage-mongodb-streams";
#[derive(Clone, Debug)]
#[cfg_attr(not(feature = "vista"), allow(dead_code))]
pub(super) struct StreamClient {
options: Option<Arc<ClientOptions>>,
pool_size: u32,
client: Arc<OnceCell<Client>>,
}
impl StreamClient {
pub(super) fn new(options: Option<ClientOptions>) -> Self {
Self {
options: options.map(Arc::new),
pool_size: DEFAULT_STREAM_POOL_SIZE,
client: Arc::new(OnceCell::new()),
}
}
}
impl MongoDB {
pub fn with_stream_pool_size(mut self, size: u32) -> Self {
self.streams.pool_size = size.max(1);
self
}
pub fn stream_pool_size(&self) -> u32 {
self.streams.pool_size
}
#[cfg(feature = "vista")]
pub(crate) async fn stream_collection(
&self,
name: &str,
) -> Result<mongodb::Collection<Document>> {
let Some(options) = &self.streams.options else {
return Ok(self.doc_collection(name));
};
let client = self
.streams
.client
.get_or_try_init(|| async {
let mut options = ClientOptions::clone(options);
let size = self.streams.pool_size;
options.max_pool_size = Some(size);
options.min_pool_size = options.min_pool_size.map(|min| min.min(size));
options.app_name = Some(STREAM_APP_NAME.to_string());
Client::with_options(options).map_err(|e| {
error!(
"Failed to build MongoDB change-stream client",
details = e.to_string()
)
})
})
.await?;
Ok(client.database(&self.database).collection(name))
}
}