fedimovies/src/database/mod.rs

84 lines
2.3 KiB
Rust
Raw Normal View History

use tokio_postgres::config::{Config as DatabaseConfig};
2022-04-08 18:52:13 +00:00
use tokio_postgres::error::{Error as PgError, SqlState};
pub mod int_enum;
pub mod json_macro;
2021-04-09 00:22:17 +00:00
pub mod migrate;
2022-01-07 16:33:23 +00:00
pub mod query_macro;
2021-04-09 00:22:17 +00:00
2022-01-06 11:09:45 +00:00
#[cfg(test)]
pub mod test_utils;
2022-12-03 21:23:52 +00:00
pub type DbPool = deadpool_postgres::Pool;
pub use tokio_postgres::{GenericClient as DatabaseClient};
2021-04-09 00:22:17 +00:00
2022-12-03 22:09:42 +00:00
#[derive(thiserror::Error, Debug)]
#[error("database type error")]
pub struct DatabaseTypeError;
#[derive(thiserror::Error, Debug)]
pub enum DatabaseError {
#[error("database pool error")]
DatabasePoolError(#[from] deadpool_postgres::PoolError),
#[error("database query error")]
DatabaseQueryError(#[from] postgres_query::Error),
#[error("database client error")]
DatabaseClientError(#[from] tokio_postgres::Error),
#[error(transparent)]
DatabaseTypeError(#[from] DatabaseTypeError),
#[error("{0} not found")]
NotFound(&'static str), // object type
#[error("{0} already exists")]
AlreadyExists(&'static str), // object type
}
pub async fn create_database_client(db_config: &DatabaseConfig)
-> tokio_postgres::Client
{
let (client, connection) = db_config.connect(tokio_postgres::NoTls)
.await.unwrap();
tokio::spawn(async move {
if let Err(err) = connection.await {
log::error!("connection error: {}", err);
};
});
client
}
2022-12-03 21:23:52 +00:00
pub fn create_pool(database_url: &str) -> DbPool {
2022-04-08 18:52:13 +00:00
let manager = deadpool_postgres::Manager::new(
database_url.parse().expect("invalid database URL"),
tokio_postgres::NoTls,
);
// https://wiki.postgresql.org/wiki/Number_Of_Database_Connections
let pool_size = num_cpus::get() * 2;
2022-12-03 21:23:52 +00:00
DbPool::builder(manager).max_size(pool_size).build().unwrap()
2021-04-09 00:22:17 +00:00
}
2022-12-03 21:23:52 +00:00
pub async fn get_database_client(db_pool: &DbPool)
2021-04-09 00:22:17 +00:00
-> Result<deadpool_postgres::Client, DatabaseError>
{
// Returns wrapped client
// https://github.com/bikeshedder/deadpool/issues/56
2022-12-03 21:23:52 +00:00
let client = db_pool.get().await?;
2021-04-09 00:22:17 +00:00
Ok(client)
}
pub fn catch_unique_violation(
object_type: &'static str,
) -> impl Fn(PgError) -> DatabaseError {
move |err| {
if let Some(code) = err.code() {
if code == &SqlState::UNIQUE_VIOLATION {
return DatabaseError::AlreadyExists(object_type);
};
};
err.into()
}
}