89 lines
1.9 KiB
Rust
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)
|
|
}
|