use std::env;
pub const DEFAULT_DATABASE_URL: &str = "database/database.sqlite";
pub const DEFAULT_SESSION_DATABASE_URL: &str = "database/sessions.sqlite";
pub const DEFAULT_POOL_LIMIT: u32 = 10;
pub const DEFAULT_USER_SNAPSHOT_INTERVAL_EVENTS: i64 = 50;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum DatabaseDriver {
Sqlite,
Postgres,
}
impl DatabaseDriver {
pub fn from_env() -> Self {
Self::parse(&env::var("DATABASE_DRIVER").unwrap_or_else(|_| "sqlite".to_string()))
}
pub fn parse(value: &str) -> Self {
match value.trim().to_ascii_lowercase().as_str() {
"postgres" | "postgresql" | "pg" => DatabaseDriver::Postgres,
_ => DatabaseDriver::Sqlite,
}
}
pub fn as_str(self) -> &'static str {
match self {
DatabaseDriver::Sqlite => "sqlite",
DatabaseDriver::Postgres => "postgres",
}
}
pub fn is_file_backed(self) -> bool {
matches!(self, DatabaseDriver::Sqlite)
}
}
pub fn database_url() -> String {
env::var("DATABASE_URL").unwrap_or_else(|_| DEFAULT_DATABASE_URL.to_string())
}
pub fn session_store_url(driver: DatabaseDriver) -> String {
match driver {
DatabaseDriver::Sqlite => database_url(),
DatabaseDriver::Postgres => env::var("SESSION_DATABASE_URL")
.unwrap_or_else(|_| DEFAULT_SESSION_DATABASE_URL.to_string()),
}
}
pub fn event_integrity_key() -> Option<Vec<u8>> {
env::var("EVENT_INTEGRITY_KEY")
.ok()
.filter(|value| !value.trim().is_empty())
.map(|value| value.into_bytes())
}
pub fn event_integrity_key_id() -> String {
env::var("EVENT_INTEGRITY_KEY_ID").unwrap_or_else(|_| "default".to_string())
}
pub fn user_snapshot_interval_events() -> Option<i64> {
let interval = env::var("USER_SNAPSHOT_INTERVAL_EVENTS")
.ok()
.filter(|value| !value.trim().is_empty())
.map(|value| {
value
.parse()
.expect("USER_SNAPSHOT_INTERVAL_EVENTS must be a number")
})
.unwrap_or(DEFAULT_USER_SNAPSHOT_INTERVAL_EVENTS);
(interval > 0).then_some(interval)
}
pub fn database_pool_limit() -> u32 {
env::var("DATABASE_POOL_LIMIT")
.unwrap_or_else(|_| DEFAULT_POOL_LIMIT.to_string())
.parse()
.expect("DATABASE_POOL_LIMIT must be a number")
}
#[cfg(test)]
mod tests {
use super::*;
use serial_test::serial;
#[test]
#[serial]
fn user_snapshot_interval_defaults_to_50() {
env::remove_var("USER_SNAPSHOT_INTERVAL_EVENTS");
assert_eq!(
user_snapshot_interval_events(),
Some(DEFAULT_USER_SNAPSHOT_INTERVAL_EVENTS)
);
}
#[test]
#[serial]
fn user_snapshot_interval_reads_env_override() {
env::set_var("USER_SNAPSHOT_INTERVAL_EVENTS", "25");
assert_eq!(user_snapshot_interval_events(), Some(25));
env::remove_var("USER_SNAPSHOT_INTERVAL_EVENTS");
}
#[test]
#[serial]
fn user_snapshot_interval_non_positive_disables_snapshots() {
env::set_var("USER_SNAPSHOT_INTERVAL_EVENTS", "0");
assert_eq!(user_snapshot_interval_events(), None);
env::remove_var("USER_SNAPSHOT_INTERVAL_EVENTS");
}
}