use std::sync::Arc;
use crate::{Environment, config::Config, health::Checks, store::Store};
#[cfg(axa_db = "postgres_sqlx")]
pub type Db = axa_postgres_sqlx::Pool;
#[cfg(axa_db = "postgres_seaorm")]
pub type Db = axa_postgres_seaorm::Pool;
#[cfg(axa_db = "postgres_diesel")]
pub type Db = axa_postgres_diesel::Pool;
#[cfg(axa_db = "postgres_toasty")]
pub type Db = axa_postgres_toasty::Pool;
#[cfg(axa_db = "mysql_sqlx")]
pub type Db = axa_mysql_sqlx::Pool;
#[cfg(axa_db = "mysql_seaorm")]
pub type Db = axa_mysql_seaorm::Pool;
#[cfg(axa_db = "mysql_diesel")]
pub type Db = axa_mysql_diesel::Pool;
#[cfg(axa_db = "mysql_toasty")]
pub type Db = axa_mysql_toasty::Pool;
#[cfg(axa_db = "sqlite_sqlx")]
pub type Db = axa_sqlite_sqlx::Pool;
#[cfg(axa_db = "sqlite_seaorm")]
pub type Db = axa_sqlite_seaorm::Pool;
#[cfg(axa_db = "sqlite_diesel")]
pub type Db = axa_sqlite_diesel::Pool;
#[cfg(axa_db = "none")]
pub type Db = ();
#[cfg(not(axa_db = "none"))]
pub async fn ping(db: &Db) -> crate::Result<()> {
#[cfg(axa_db = "postgres_sqlx")]
axa_postgres_sqlx::ping(db).await?;
#[cfg(axa_db = "postgres_seaorm")]
axa_postgres_seaorm::ping(db).await?;
#[cfg(axa_db = "postgres_diesel")]
axa_postgres_diesel::ping(db).await?;
#[cfg(axa_db = "postgres_toasty")]
axa_postgres_toasty::ping(db).await?;
#[cfg(axa_db = "mysql_sqlx")]
axa_mysql_sqlx::ping(db).await?;
#[cfg(axa_db = "mysql_seaorm")]
axa_mysql_seaorm::ping(db).await?;
#[cfg(axa_db = "mysql_diesel")]
axa_mysql_diesel::ping(db).await?;
#[cfg(axa_db = "mysql_toasty")]
axa_mysql_toasty::ping(db).await?;
#[cfg(axa_db = "sqlite_sqlx")]
axa_sqlite_sqlx::ping(db).await?;
#[cfg(axa_db = "sqlite_seaorm")]
axa_sqlite_seaorm::ping(db).await?;
#[cfg(axa_db = "sqlite_diesel")]
axa_sqlite_diesel::ping(db).await?;
Ok(())
}
#[cfg(all(
test,
any(
axa_db = "postgres_sqlx",
axa_db = "mysql_sqlx",
axa_db = "sqlite_sqlx"
)
))]
fn test_db() -> Db {
static RUNTIME: std::sync::LazyLock<tokio::runtime::Runtime> =
std::sync::LazyLock::new(|| tokio::runtime::Runtime::new().expect("a runtime"));
let _entered = RUNTIME.enter();
let options =
sqlx::pool::PoolOptions::new().acquire_timeout(std::time::Duration::from_millis(50));
#[cfg(axa_db = "postgres_sqlx")]
let uri = "postgres://axa:axa@127.0.0.1:1/axa";
#[cfg(axa_db = "mysql_sqlx")]
let uri = "mysql://axa:axa@127.0.0.1:1/axa";
#[cfg(axa_db = "sqlite_sqlx")]
let uri = "sqlite:///axa-no-such-folder/never.sqlite3";
options.connect_lazy(uri).expect("a well-formed address")
}
#[cfg(all(
test,
any(
axa_db = "postgres_seaorm",
axa_db = "mysql_seaorm",
axa_db = "sqlite_seaorm"
)
))]
fn test_db() -> Db {
sea_orm::DatabaseConnection::default()
}
#[cfg(all(test, axa_db = "postgres_diesel"))]
fn test_db() -> Db {
let config = axa_postgres_diesel::PoolConfig {
wait_timeout: std::time::Duration::from_millis(50),
..axa_postgres_diesel::PoolConfig::new("postgres://axa:axa@127.0.0.1:1/axa")
};
let tls = axa_postgres_diesel::web_tls().expect("TLS settings");
axa_postgres_diesel::pool_with_tls(&config, tls).expect("a pool that never connects")
}
#[cfg(all(test, axa_db = "mysql_diesel"))]
fn test_db() -> Db {
let config = axa_mysql_diesel::PoolConfig {
wait_timeout: std::time::Duration::from_millis(50),
..axa_mysql_diesel::PoolConfig::new("mysql://axa:axa@127.0.0.1:1/axa")
};
axa_mysql_diesel::pool(&config).expect("a pool that never connects")
}
#[cfg(all(test, axa_db = "sqlite_diesel"))]
fn test_db() -> Db {
let config = axa_sqlite_diesel::PoolConfig {
wait_timeout: std::time::Duration::from_millis(50),
..axa_sqlite_diesel::PoolConfig::new("sqlite:///axa-no-such-folder/never.sqlite3")
};
axa_sqlite_diesel::pool(&config).expect("a pool that never connects")
}
#[cfg(all(test, any(axa_db = "postgres_toasty", axa_db = "mysql_toasty")))]
fn test_db() -> Db {
unimplemented!(
"Toasty connects when its handle is made, so a unit test with Toasty as the only \
database feature has no context"
)
}
#[cfg(all(test, axa_db = "none"))]
fn test_db() -> Db {}
#[derive(Clone)]
pub struct AppContext {
pub environment: Environment,
pub db: Db,
pub config: Arc<Config>,
pub shared_store: Arc<Store>,
pub health_checks: Checks,
#[cfg(feature = "queue")]
pub queue_provider: Option<Arc<crate::queue::Queue>>,
}
impl std::fmt::Debug for AppContext {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut debug = f.debug_struct("AppContext");
debug
.field("environment", &self.environment)
.field("db", &std::any::type_name::<Db>())
.field("config", &self.config)
.field("shared_store", &self.shared_store)
.field("health_checks", &self.health_checks);
#[cfg(feature = "queue")]
debug.field("queue_provider", &self.queue_provider);
debug.finish()
}
}
impl AppContext {
#[must_use]
pub fn new(environment: Environment, db: Db, config: Config) -> Self {
Self {
environment,
db,
config: Arc::new(config),
shared_store: Arc::new(Store::default()),
health_checks: Checks::new(),
#[cfg(feature = "queue")]
queue_provider: None,
}
}
#[cfg(test)]
#[allow(clippy::unit_arg, dead_code)]
pub(crate) fn for_test(environment: Environment, config: Config) -> Self {
Self::new(environment, test_db(), config)
}
}