//! Postgres persistence for TeamClaw. //! //! Queries are compile-time checked (`sqlx::query!`) against the schema in //! `/migrations`, and every repository is tested only against a real //! Postgres via `tc-testkit` — no in-memory store exists. pub mod repo; use sqlx::postgres::PgPoolOptions; use sqlx::PgPool; /// All schema migrations, embedded so binaries can self-migrate at boot. pub static MIGRATOR: sqlx::migrate::Migrator = sqlx::migrate!("../../migrations"); #[derive(Debug, thiserror::Error)] pub enum DbError { #[error("not found")] NotFound, #[error("conflict: {0}")] Conflict(String), #[error(transparent)] Other(sqlx::Error), } impl From for DbError { fn from(err: sqlx::Error) -> Self { match &err { sqlx::Error::RowNotFound => DbError::NotFound, sqlx::Error::Database(db) if db.is_unique_violation() => { DbError::Conflict(db.message().to_owned()) } _ => DbError::Other(err), } } } /// Connects a pool sized from configuration. Callers run `MIGRATOR` at boot. pub async fn connect(url: &str, max_connections: u32) -> Result { Ok(PgPoolOptions::new() .max_connections(max_connections) .connect(url) .await?) }