use crate::{
Db, Result,
db::{Connect, Pool, Shared, pool::PoolConfig},
engine::Engine,
};
use toasty_core::{
driver::Driver,
schema::{
self,
app::{self, ModelSet},
},
};
use std::{sync::Arc, time::Duration};
#[derive(Default)]
pub struct Builder {
models: app::ModelSet,
core: schema::Builder,
pool: PoolConfig,
}
impl Builder {
pub fn models(&mut self, models: ModelSet) -> &mut Self {
self.models = models;
self
}
pub fn table_name_prefix(&mut self, prefix: &str) -> &mut Self {
self.core.table_name_prefix(prefix);
self
}
pub fn max_pool_size(&mut self, max_size: usize) -> &mut Self {
self.pool.max_size = max_size;
self
}
pub fn pool_wait_timeout(&mut self, timeout: Option<Duration>) -> &mut Self {
self.pool.timeouts.wait = timeout;
self
}
pub fn pool_create_timeout(&mut self, timeout: Option<Duration>) -> &mut Self {
self.pool.timeouts.create = timeout;
self
}
pub fn build_app_schema(&self) -> Result<app::Schema> {
app::Schema::from_macro(self.models.clone())
}
pub async fn connect(&mut self, url: &str) -> Result<Db> {
let con = Connect::new(url).await?;
self.build(con).await
}
pub async fn build(&mut self, driver: impl Driver) -> Result<Db> {
tracing::info!(models = self.models.len(), "building database schema");
let capability = driver.capability();
capability.validate()?;
let schema = self.core.build(self.build_app_schema()?, capability)?;
tracing::info!(tables = schema.db.tables.len(), "schema built successfully");
let engine = Engine::new(Arc::new(schema), capability);
let pool = Pool::new(driver, engine.clone(), self.pool.clone())?;
let shared = Arc::new(Shared { engine, pool });
let conn = shared.pool.get(shared.clone()).await?;
std::mem::drop(conn);
tracing::info!("database ready");
Ok(Db { shared })
}
}