use std::sync::Arc;
use std::time::Duration;
use async_lock::OnceCell;
use azure_data_cosmos_driver::driver::{CosmosDriverRuntime, CosmosDriverRuntimeBuilder};
use crate::options::{ConnectionPoolOptions, OperationOptions, UserAgentSuffix};
#[derive(Clone, Debug)]
pub struct CosmosRuntime(Arc<CosmosDriverRuntime>);
impl CosmosRuntime {
pub fn builder() -> CosmosRuntimeBuilder {
CosmosRuntimeBuilder::new()
}
pub(crate) async fn global() -> crate::Result<Self> {
static GLOBAL: OnceCell<CosmosRuntime> = OnceCell::new();
GLOBAL
.get_or_try_init(|| async { CosmosRuntimeBuilder::new().build().await })
.await
.cloned()
}
pub(crate) fn into_inner(self) -> Arc<CosmosDriverRuntime> {
self.0
}
}
#[derive(Default, Debug, Clone)]
pub struct CosmosRuntimeBuilder(CosmosDriverRuntimeBuilder);
impl CosmosRuntimeBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn with_connection_pool(mut self, options: ConnectionPoolOptions) -> Self {
self.0 = self.0.with_connection_pool(options);
self
}
pub fn with_default_operation_options(mut self, options: OperationOptions) -> Self {
self.0 = self.0.with_default_operation_options(options);
self
}
pub fn with_user_agent_suffix(mut self, suffix: UserAgentSuffix) -> Self {
self.0 = self.0.with_user_agent_suffix(suffix);
self
}
pub fn with_cpu_refresh_interval(mut self, interval: Duration) -> Self {
self.0 = self.0.with_cpu_refresh_interval(interval);
self
}
pub async fn build(self) -> crate::Result<CosmosRuntime> {
let mut inner = self.0;
inner = inner.with_wrapping_sdk_identifier(format!(
"azsdk-rust-cosmos/{}",
env!("CARGO_PKG_VERSION")
));
let runtime = inner.build().await.map_err(crate::CosmosError::from)?;
Ok(CosmosRuntime(runtime))
}
}
impl From<CosmosDriverRuntimeBuilder> for CosmosRuntimeBuilder {
fn from(value: CosmosDriverRuntimeBuilder) -> Self {
Self(value)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn global_returns_same_runtime_across_calls() {
let a = CosmosRuntime::global().await.expect("global builds");
let b = CosmosRuntime::global().await.expect("global builds");
assert!(
Arc::ptr_eq(&a.0, &b.0),
"global() must return the same Arc on repeated calls"
);
}
#[tokio::test]
async fn builder_applies_wrapping_sdk_identifier() {
let runtime = CosmosRuntime::builder()
.build()
.await
.expect("runtime builds");
let ua = runtime.0.user_agent().as_str().to_string();
assert!(
ua.contains("azsdk-rust-cosmos/"),
"user agent {ua:?} should contain the wrapping SDK identifier"
);
}
}