use std::time::Duration;
use crate::config::{Config, Serializer};
use crate::sysdb::{SystemDatabase, postgres};
use crate::{ClientConfig, Error, Result};
pub(crate) struct Connection {
sysdb: Box<dyn SystemDatabase>,
serializer: Serializer,
app_name: Option<String>,
outcome_poll_interval: Duration,
owner: Owner,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum Owner {
Application,
Client,
}
impl Connection {
pub(crate) async fn for_application(
config: &Config,
executor_id: &str,
app_name: &str,
) -> Result<Self> {
let sysdb = postgres::PostgresSystemDatabase::connect(&postgres::Config {
url: &config.database_url,
max_connections: config.max_connections,
use_listen_notify: config.use_listen_notify,
migrate: config.migrate,
settings: postgres::Settings {
schema: &config.schema,
executor_id: Some(executor_id),
application_name: Some(app_name),
polling_concurrency: config.polling_concurrency,
notification_coalesce: config.notification_coalesce,
..postgres::Settings::default()
},
})
.await
.map_err(Error::SystemDatabase)?;
Ok(Self {
sysdb: Box::new(sysdb),
serializer: config.serializer.clone(),
app_name: Some(app_name.to_owned()),
outcome_poll_interval: config.outcome_poll_interval(),
owner: Owner::Application,
})
}
pub(crate) async fn for_client(config: &ClientConfig) -> Result<Self> {
config.validate()?;
let sysdb = postgres::PostgresSystemDatabase::connect(&postgres::Config {
url: &config.database_url,
max_connections: config.max_connections,
use_listen_notify: config.use_listen_notify,
migrate: false,
settings: postgres::Settings {
schema: &config.schema,
executor_id: None,
application_name: config.app_name.as_deref(),
polling_concurrency: config.polling_concurrency,
notification_coalesce: config.notification_coalesce,
..postgres::Settings::default()
},
})
.await
.map_err(Error::SystemDatabase)?;
tracing::info!(
app_name = config.app_name.as_deref().unwrap_or("<none>"),
"DBOS client connected"
);
Ok(Self {
sysdb: Box::new(sysdb),
serializer: config.serializer.clone(),
app_name: config.app_name.clone(),
outcome_poll_interval: config.outcome_poll_interval(),
owner: Owner::Client,
})
}
pub(crate) fn sysdb(&self) -> &dyn SystemDatabase {
&*self.sysdb
}
pub(crate) fn serializer(&self) -> &Serializer {
&self.serializer
}
pub(crate) fn app_name(&self) -> Option<&str> {
self.app_name.as_deref()
}
pub(crate) fn outcome_poll_interval(&self) -> Duration {
self.outcome_poll_interval
}
pub(crate) fn owner(&self) -> Owner {
self.owner
}
pub(crate) async fn close(&self) {
self.sysdb.close().await;
}
}
impl std::fmt::Debug for Connection {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Connection")
.field("app_name", &self.app_name)
.field("serializer", &self.serializer)
.finish_non_exhaustive()
}
}