Files
leadcast/backend/src/db/mod.rs
T
2026-07-26 21:12:38 -03:00

89 lines
1.9 KiB
Rust

use std::{error::Error, fmt::Display};
use deadpool_postgres::{Object, Pool};
use serde::{Deserialize, Serialize};
use crate::error::{AppError, AppResult};
pub mod models;
pub mod querys;
#[derive(Clone)]
pub struct Db {
pool: Pool,
}
impl Db {
pub fn new(pool: Pool) -> Self {
Self { pool }
}
pub fn pool(&self) -> &Pool {
&self.pool
}
pub async fn client(&self) -> AppResult<Object> {
self.pool.get().await.map_err(db_error)
}
pub async fn health(&self) -> AppResult<()> {
let client = self.client().await?;
client.simple_query("SELECT 1").await.map_err(db_error)?;
Ok(())
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct Pagination {
pub limit: i64,
pub offset: i64,
}
impl Pagination {
pub const DEFAULT_LIMIT: i64 = 50;
pub const MAX_LIMIT: i64 = 250;
pub fn new(limit: i64, offset: i64) -> Self {
Self {
limit: limit.clamp(1, Self::MAX_LIMIT),
offset: offset.max(0),
}
}
}
impl Default for Pagination {
fn default() -> Self {
Self::new(Self::DEFAULT_LIMIT, 0)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Page<T> {
pub items: Vec<T>,
pub total: i64,
pub limit: i64,
pub offset: i64,
}
impl<T> Page<T> {
pub fn new(items: Vec<T>, total: i64, pagination: Pagination) -> Self {
Self {
items,
total,
limit: pagination.limit,
offset: pagination.offset,
}
}
}
pub(crate) fn db_error(error: impl Display + Error) -> AppError {
let mut message = error.to_string();
let mut source = error.source();
while let Some(cause) = source {
message.push_str(": ");
message.push_str(&cause.to_string());
source = cause.source();
}
AppError::Database(message)
}