use sqlx::{postgres::PgPoolOptions, Error, Executor as _, Pool, Postgres, Transaction};
use std::env;
pub struct DBClient {
pool: Pool<Postgres>,
}
impl DBClient {
pub async fn new() -> Result<Self, sqlx::Error> {
let db_uri = env::var("DATABASE_URL").unwrap();
let db_max_conn: u32 = env::var("DATABASE_MAX_CONN")
.unwrap()
.parse::<u32>()
.unwrap();
let pool = PgPoolOptions::new()
.max_connections(db_max_conn)
.after_connect(|conn| {
Box::pin(async move {
conn.execute("SET default_transaction_isolation TO 'serializable'")
.await?;
Ok(())
})
})
.connect(&db_uri)
.await?;
pool.execute("CREATE TABLE IF NOT EXISTS checkouts (id varchar PRIMARY KEY, data jsonb)")
.await?;
pool.execute("CREATE TABLE IF NOT EXISTS payments (id varchar PRIMARY KEY, correlation_id varchar, data jsonb)")
.await?;
pool.execute("CREATE TABLE IF NOT EXISTS orders (id varchar PRIMARY KEY, data jsonb)")
.await?;
pool.execute("CREATE INDEX IF NOT EXISTS checkout_state_index ON checkouts((data->state->>'name'))")
.await?;
pool.execute("CREATE INDEX IF NOT EXISTS payment_state_index ON payments((data->state->>'name'))")
.await?;
pool.execute("CREATE INDEX IF NOT EXISTS order_state_index ON orders((data->state->>'name'))")
.await?;
Ok(Self { pool })
}
pub async fn new_tx<'a>(&'a self) -> Result<Transaction<'a, Postgres>, Error> {
self.pool.begin().await
}
}