refactor: extract pg_repo macro and MapDomainError trait to reduce postgres adapter boilerplate

This commit is contained in:
2026-05-31 18:24:16 +02:00
parent 2fe0a4c245
commit c16c9d4581
9 changed files with 144 additions and 249 deletions

View File

@@ -1,4 +1,4 @@
use crate::db::PgPool;
use crate::helpers::{pg_repo, MapDomainError};
use async_trait::async_trait;
use chrono::{DateTime, Utc};
use domain::{
@@ -40,15 +40,7 @@ impl From<StorageVolumeRow> for StorageVolume {
}
}
pub struct PostgresStorageVolumeRepository {
pool: PgPool,
}
impl PostgresStorageVolumeRepository {
pub fn new(pool: PgPool) -> Self {
Self { pool }
}
}
pg_repo!(PostgresStorageVolumeRepository);
#[async_trait]
impl StorageVolumeRepository for PostgresStorageVolumeRepository {
@@ -60,7 +52,7 @@ impl StorageVolumeRepository for PostgresStorageVolumeRepository {
.bind(*id.as_uuid())
.fetch_optional(&self.pool)
.await
.map_err(|e| DomainError::Internal(e.to_string()))?;
.map_pg()?;
Ok(row.map(Into::into))
}
@@ -72,7 +64,7 @@ impl StorageVolumeRepository for PostgresStorageVolumeRepository {
)
.fetch_all(&self.pool)
.await
.map_err(|e| DomainError::Internal(e.to_string()))?;
.map_pg()?;
Ok(rows.into_iter().map(Into::into).collect())
}
@@ -94,7 +86,7 @@ impl StorageVolumeRepository for PostgresStorageVolumeRepository {
.bind(volume.available_bytes as i64)
.execute(&self.pool)
.await
.map_err(|e| DomainError::Internal(e.to_string()))?;
.map_pg()?;
Ok(())
}
@@ -103,7 +95,7 @@ impl StorageVolumeRepository for PostgresStorageVolumeRepository {
.bind(*id.as_uuid())
.execute(&self.pool)
.await
.map_err(|e| DomainError::Internal(e.to_string()))?;
.map_pg()?;
Ok(())
}
}
@@ -151,15 +143,7 @@ impl From<LibraryPathRow> for LibraryPath {
}
}
pub struct PostgresLibraryPathRepository {
pool: PgPool,
}
impl PostgresLibraryPathRepository {
pub fn new(pool: PgPool) -> Self {
Self { pool }
}
}
pg_repo!(PostgresLibraryPathRepository);
#[async_trait]
impl LibraryPathRepository for PostgresLibraryPathRepository {
@@ -171,7 +155,7 @@ impl LibraryPathRepository for PostgresLibraryPathRepository {
.bind(*id.as_uuid())
.fetch_optional(&self.pool)
.await
.map_err(|e| DomainError::Internal(e.to_string()))?;
.map_pg()?;
Ok(row.map(Into::into))
}
@@ -184,7 +168,7 @@ impl LibraryPathRepository for PostgresLibraryPathRepository {
.bind(*volume_id.as_uuid())
.fetch_all(&self.pool)
.await
.map_err(|e| DomainError::Internal(e.to_string()))?;
.map_pg()?;
Ok(rows.into_iter().map(Into::into).collect())
}
@@ -201,7 +185,7 @@ impl LibraryPathRepository for PostgresLibraryPathRepository {
.bind(*owner_id.as_uuid())
.fetch_all(&self.pool)
.await
.map_err(|e| DomainError::Internal(e.to_string()))?;
.map_pg()?;
Ok(rows.into_iter().map(Into::into).collect())
}
@@ -225,7 +209,7 @@ impl LibraryPathRepository for PostgresLibraryPathRepository {
.bind(path.designated_owner_id.as_ref().map(|id| *id.as_uuid()))
.execute(&self.pool)
.await
.map_err(|e| DomainError::Internal(e.to_string()))?;
.map_pg()?;
Ok(())
}
@@ -234,7 +218,7 @@ impl LibraryPathRepository for PostgresLibraryPathRepository {
.bind(*id.as_uuid())
.execute(&self.pool)
.await
.map_err(|e| DomainError::Internal(e.to_string()))?;
.map_pg()?;
Ok(())
}
}
@@ -294,15 +278,7 @@ impl TryFrom<IngestSessionRow> for IngestSession {
}
}
pub struct PostgresIngestSessionRepository {
pool: PgPool,
}
impl PostgresIngestSessionRepository {
pub fn new(pool: PgPool) -> Self {
Self { pool }
}
}
pg_repo!(PostgresIngestSessionRepository);
#[async_trait]
impl IngestSessionRepository for PostgresIngestSessionRepository {
@@ -315,7 +291,7 @@ impl IngestSessionRepository for PostgresIngestSessionRepository {
.bind(*id.as_uuid())
.fetch_optional(&self.pool)
.await
.map_err(|e| DomainError::Internal(e.to_string()))?;
.map_pg()?;
row.map(TryInto::try_into).transpose()
}
@@ -329,7 +305,7 @@ impl IngestSessionRepository for PostgresIngestSessionRepository {
.bind(*user_id.as_uuid())
.fetch_all(&self.pool)
.await
.map_err(|e| DomainError::Internal(e.to_string()))?;
.map_pg()?;
rows.into_iter().map(TryInto::try_into).collect()
}
@@ -354,7 +330,7 @@ impl IngestSessionRepository for PostgresIngestSessionRepository {
.bind(session.error_message.as_deref())
.execute(&self.pool)
.await
.map_err(|e| DomainError::Internal(e.to_string()))?;
.map_pg()?;
Ok(())
}
}
@@ -457,15 +433,7 @@ impl From<UsageLedgerRow> for UsageLedgerEntry {
}
}
pub struct PostgresQuotaRepository {
pool: PgPool,
}
impl PostgresQuotaRepository {
pub fn new(pool: PgPool) -> Self {
Self { pool }
}
}
pg_repo!(PostgresQuotaRepository);
#[async_trait]
impl QuotaRepository for PostgresQuotaRepository {
@@ -479,7 +447,7 @@ impl QuotaRepository for PostgresQuotaRepository {
.bind(*owner_id.as_uuid())
.fetch_optional(&self.pool)
.await
.map_err(|e| DomainError::Internal(e.to_string()))?;
.map_pg()?;
let Some(def) = def_row else {
return Ok(None);
@@ -492,7 +460,7 @@ impl QuotaRepository for PostgresQuotaRepository {
.bind(def.quota_id)
.fetch_all(&self.pool)
.await
.map_err(|e| DomainError::Internal(e.to_string()))?;
.map_pg()?;
Ok(Some(QuotaDefinition {
quota_id: SystemId::from_uuid(def.quota_id),
@@ -515,14 +483,14 @@ impl QuotaRepository for PostgresQuotaRepository {
.bind(quota.is_enforced)
.execute(&self.pool)
.await
.map_err(|e| DomainError::Internal(e.to_string()))?;
.map_pg()?;
// Delete old rules then re-insert
sqlx::query("DELETE FROM quota_rules WHERE quota_id = $1")
.bind(*quota.quota_id.as_uuid())
.execute(&self.pool)
.await
.map_err(|e| DomainError::Internal(e.to_string()))?;
.map_pg()?;
for rule in &quota.rules {
sqlx::query(
@@ -537,7 +505,7 @@ impl QuotaRepository for PostgresQuotaRepository {
.bind(rule.is_unlimited)
.execute(&self.pool)
.await
.map_err(|e| DomainError::Internal(e.to_string()))?;
.map_pg()?;
}
Ok(())
@@ -549,20 +517,12 @@ impl QuotaRepository for PostgresQuotaRepository {
.bind(*id.as_uuid())
.execute(&self.pool)
.await
.map_err(|e| DomainError::Internal(e.to_string()))?;
.map_pg()?;
Ok(())
}
}
pub struct PostgresUsageLedgerRepository {
pool: PgPool,
}
impl PostgresUsageLedgerRepository {
pub fn new(pool: PgPool) -> Self {
Self { pool }
}
}
pg_repo!(PostgresUsageLedgerRepository);
#[async_trait]
impl UsageLedgerRepository for PostgresUsageLedgerRepository {
@@ -579,7 +539,7 @@ impl UsageLedgerRepository for PostgresUsageLedgerRepository {
.bind(&entry.context)
.execute(&self.pool)
.await
.map_err(|e| DomainError::Internal(e.to_string()))?;
.map_pg()?;
Ok(())
}
@@ -600,7 +560,7 @@ impl UsageLedgerRepository for PostgresUsageLedgerRepository {
.bind(since_dt)
.fetch_one(&self.pool)
.await
.map_err(|e| DomainError::Internal(e.to_string()))?;
.map_pg()?;
Ok(row.total as u64)
}