pub(crate) mod db; pub(crate) mod models; use std::fmt::{Debug, Display}; use serde::{Deserialize, Serialize}; #[derive(Debug)] pub(crate) enum DbError { NotFound, Other(eyre::Report), } impl Display for DbError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { DbError::NotFound => write!(f, "Not found"), DbError::Other(report) => write!(f, "Other: {report}"), } } } impl From for DbError { fn from(error: time::error::ComponentRange) -> Self { DbError::Other(error.into()) } } impl From for DbError { fn from(error: time::error::Error) -> Self { DbError::Other(error.into()) } } impl From for DbError { fn from(error: sqlx::Error) -> Self { match error { sqlx::Error::RowNotFound => DbError::NotFound, error => DbError::Other(error.into()), } } } impl std::error::Error for DbError {} pub(crate) type DbResult = Result; #[derive(Debug, PartialEq)] pub(crate) enum DbType { Postgres, Unknown, } #[derive(Clone, Deserialize, Serialize)] pub(crate) struct DbSettings { pub(crate) db_uri: String, /// Optional URI for read replicas. If set, read-only queries will use this connection. pub(crate) read_db_uri: Option, } impl DbSettings { pub(crate) fn db_type(&self) -> DbType { if self.db_uri.starts_with("postgres://") || self.db_uri.starts_with("postgresql://") { DbType::Postgres } else { DbType::Unknown } } } fn redact_db_uri(uri: &str) -> String { url::Url::parse(uri) .map(|mut url| { let _ = url.set_password(Some("****")); url.to_string() }) .unwrap_or_else(|_| uri.to_string()) } // Do our best to redact passwords so they're not logged in the event of an error. impl Debug for DbSettings { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { if self.db_type() == DbType::Postgres { let redacted_uri = redact_db_uri(&self.db_uri); let redacted_read_uri = self.read_db_uri.as_ref().map(|uri| redact_db_uri(uri)); f.debug_struct("DbSettings") .field("db_uri", &redacted_uri) .field("read_db_uri", &redacted_read_uri) .finish() } else { f.debug_struct("DbSettings") .field("db_uri", &self.db_uri) .field("read_db_uri", &self.read_db_uri) .finish() } } }