Skip to main content

platform_core/
db.rs

1use crate::config::DatabaseConfig;
2use crate::error::{AppError, AppResult, ErrorCode};
3use sqlx::postgres::PgPoolOptions;
4use sqlx::{PgPool, Postgres, Transaction};
5
6pub type DbPool = PgPool;
7pub type DbTransaction<'a> = Transaction<'a, Postgres>;
8
9pub async fn connect_pool(config: &DatabaseConfig) -> AppResult<DbPool> {
10    PgPoolOptions::new()
11        .max_connections(config.max_connections)
12        .connect(&config.url)
13        .await
14        .map_err(|source| {
15            AppError::new(ErrorCode::ExternalDependency, "Database connection failed")
16                .with_source(source)
17                .retryable()
18        })
19}
20
21pub async fn ping(pool: &DbPool) -> AppResult<()> {
22    sqlx::query("select 1")
23        .execute(pool)
24        .await
25        .map(|_| ())
26        .map_err(|source| {
27            AppError::new(
28                ErrorCode::ExternalDependency,
29                "Database health check failed",
30            )
31            .with_source(source)
32            .retryable()
33        })
34}
35
36pub async fn begin_transaction(pool: &DbPool) -> AppResult<DbTransaction<'_>> {
37    pool.begin().await.map_err(map_transaction_error)
38}
39
40pub async fn commit_transaction(transaction: DbTransaction<'_>) -> AppResult<()> {
41    transaction.commit().await.map_err(map_transaction_error)
42}
43
44pub async fn rollback_transaction(transaction: DbTransaction<'_>) -> AppResult<()> {
45    transaction.rollback().await.map_err(map_transaction_error)
46}
47
48fn map_transaction_error(source: sqlx::Error) -> AppError {
49    AppError::new(ErrorCode::Internal, "Database transaction failed").with_source(source)
50}