2022-04-18 22:07:52 +02:00
|
|
|
use actix::{Actor, Context};
|
2022-05-06 11:47:18 +02:00
|
|
|
use config::SharedAppConfig;
|
2022-04-18 22:07:52 +02:00
|
|
|
use sqlx::PgPool;
|
2022-05-06 16:02:38 +02:00
|
|
|
|
|
|
|
pub use crate::account_orders::*;
|
|
|
|
pub use crate::accounts::*;
|
|
|
|
pub use crate::order_items::*;
|
|
|
|
pub use crate::photos::*;
|
|
|
|
pub use crate::product_photos::*;
|
|
|
|
pub use crate::products::*;
|
|
|
|
pub use crate::shopping_cart_items::*;
|
|
|
|
pub use crate::shopping_carts::*;
|
|
|
|
pub use crate::stocks::*;
|
|
|
|
pub use crate::tokens::*;
|
2022-04-14 21:40:26 +02:00
|
|
|
|
2022-04-16 18:57:37 +02:00
|
|
|
pub mod account_orders;
|
|
|
|
pub mod accounts;
|
|
|
|
pub mod order_items;
|
2022-05-06 16:02:38 +02:00
|
|
|
pub mod photos;
|
|
|
|
pub mod product_photos;
|
2022-04-16 18:57:37 +02:00
|
|
|
pub mod products;
|
|
|
|
pub mod shopping_cart_items;
|
|
|
|
pub mod shopping_carts;
|
|
|
|
pub mod stocks;
|
2022-04-18 22:07:52 +02:00
|
|
|
pub mod tokens;
|
2022-04-14 21:40:26 +02:00
|
|
|
|
2022-04-20 14:30:59 +02:00
|
|
|
#[macro_export]
|
|
|
|
macro_rules! db_async_handler {
|
|
|
|
($msg: ty, $async: ident, $res: ty) => {
|
2022-05-06 16:02:38 +02:00
|
|
|
impl actix::Handler<$msg> for crate::Database {
|
2022-04-20 14:30:59 +02:00
|
|
|
type Result = actix::ResponseActFuture<Self, Result<$res>>;
|
|
|
|
|
|
|
|
fn handle(&mut self, msg: $msg, _ctx: &mut Self::Context) -> Self::Result {
|
|
|
|
use actix::WrapFuture;
|
|
|
|
let pool = self.pool.clone();
|
|
|
|
Box::pin(async { $async(msg, pool).await }.into_actor(self))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2022-05-04 22:26:10 +02:00
|
|
|
($msg: ty, $async: ident, $res: ty, $inner_async: ident) => {
|
|
|
|
async fn $inner_async(msg: $msg, pool: sqlx::PgPool) -> Result<$res> {
|
|
|
|
let mut t = pool.begin().await?;
|
|
|
|
match $async(msg, &mut t).await {
|
|
|
|
Ok(res) => {
|
|
|
|
t.commit().await?;
|
|
|
|
Ok(res)
|
|
|
|
}
|
|
|
|
Err(e) => {
|
|
|
|
let _ = t.rollback().await;
|
|
|
|
Err(e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-06 16:02:38 +02:00
|
|
|
impl actix::Handler<$msg> for crate::Database {
|
2022-05-04 22:26:10 +02:00
|
|
|
type Result = actix::ResponseActFuture<Self, Result<$res>>;
|
|
|
|
|
|
|
|
fn handle(&mut self, msg: $msg, _ctx: &mut Self::Context) -> Self::Result {
|
|
|
|
use actix::WrapFuture;
|
|
|
|
let pool = self.pool.clone();
|
|
|
|
Box::pin(async { $inner_async(msg, pool).await }.into_actor(self))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2022-04-20 14:30:59 +02:00
|
|
|
}
|
|
|
|
|
2022-05-04 07:26:29 +02:00
|
|
|
#[macro_export]
|
|
|
|
macro_rules! query_db {
|
|
|
|
($db: expr, $msg: expr, default $fail: expr) => {
|
|
|
|
match $db.send($msg).await {
|
|
|
|
Ok(Ok(r)) => r,
|
|
|
|
Ok(Err(e)) => {
|
|
|
|
log::error!("{e}");
|
|
|
|
$fail
|
|
|
|
}
|
|
|
|
Err(e) => {
|
|
|
|
log::error!("{e:?}");
|
|
|
|
$fail
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
($db: expr, $msg: expr, $fail: expr) => {
|
|
|
|
$crate::query_db!($db, $msg, $fail, $fail)
|
|
|
|
};
|
|
|
|
|
|
|
|
($db: expr, $msg: expr, $db_fail: expr, $act_fail: expr) => {
|
|
|
|
match $db.send($msg).await {
|
|
|
|
Ok(Ok(r)) => r,
|
|
|
|
Ok(Err(e)) => {
|
|
|
|
log::error!("{e}");
|
|
|
|
return Err($db_fail);
|
|
|
|
}
|
|
|
|
Err(e) => {
|
|
|
|
log::error!("{e:?}");
|
|
|
|
return Err($act_fail);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-04-14 21:40:26 +02:00
|
|
|
#[derive(Debug, thiserror::Error)]
|
|
|
|
pub enum Error {
|
|
|
|
#[error("Failed to connect to database. {0:?}")]
|
2022-04-18 22:07:52 +02:00
|
|
|
Connect(#[from] sqlx::Error),
|
|
|
|
#[error("{0}")]
|
|
|
|
Account(#[from] accounts::Error),
|
2022-04-14 21:40:26 +02:00
|
|
|
#[error("{0}")]
|
2022-04-18 22:07:52 +02:00
|
|
|
AccountOrder(#[from] account_orders::Error),
|
2022-04-14 21:40:26 +02:00
|
|
|
#[error("{0}")]
|
2022-04-18 22:07:52 +02:00
|
|
|
Product(#[from] products::Error),
|
2022-04-16 06:58:48 +02:00
|
|
|
#[error("{0}")]
|
2022-04-18 22:07:52 +02:00
|
|
|
Stock(#[from] stocks::Error),
|
2022-04-15 17:04:23 +02:00
|
|
|
#[error("{0}")]
|
2022-04-18 22:07:52 +02:00
|
|
|
OrderItem(#[from] order_items::Error),
|
2022-04-16 07:31:19 +02:00
|
|
|
#[error("{0}")]
|
2022-04-18 22:07:52 +02:00
|
|
|
ShoppingCart(#[from] shopping_carts::Error),
|
2022-04-16 09:30:11 +02:00
|
|
|
#[error("{0}")]
|
2022-04-18 22:07:52 +02:00
|
|
|
ShoppingCartItem(#[from] shopping_cart_items::Error),
|
2022-04-16 12:48:38 +02:00
|
|
|
#[error("{0}")]
|
2022-04-18 22:07:52 +02:00
|
|
|
Token(#[from] tokens::Error),
|
2022-05-06 16:02:38 +02:00
|
|
|
#[error("{0}")]
|
|
|
|
Photo(#[from] photos::Error),
|
|
|
|
#[error("{0}")]
|
|
|
|
ProductPhoto(#[from] product_photos::Error),
|
2022-04-14 21:40:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pub type Result<T> = std::result::Result<T, Error>;
|
|
|
|
|
|
|
|
pub struct Database {
|
|
|
|
pool: PgPool,
|
|
|
|
}
|
|
|
|
|
2022-04-20 14:30:59 +02:00
|
|
|
pub type SharedDatabase = actix::Addr<Database>;
|
|
|
|
|
2022-04-14 21:40:26 +02:00
|
|
|
impl Clone for Database {
|
|
|
|
fn clone(&self) -> Self {
|
2022-04-18 22:07:52 +02:00
|
|
|
Self {
|
|
|
|
pool: self.pool.clone(),
|
|
|
|
}
|
2022-04-14 21:40:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Database {
|
2022-05-06 11:47:18 +02:00
|
|
|
pub async fn build(config: SharedAppConfig) -> Result<Self> {
|
2022-04-28 15:54:18 +02:00
|
|
|
let url = config.lock().database().url();
|
|
|
|
let pool = sqlx::PgPool::connect(&url).await.map_err(Error::Connect)?;
|
2022-04-14 21:40:26 +02:00
|
|
|
Ok(Database { pool })
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn pool(&self) -> &PgPool {
|
|
|
|
&self.pool
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Actor for Database {
|
|
|
|
type Context = Context<Self>;
|
|
|
|
}
|