spiffbot/src/databases/mod.rs
2025-03-23 13:53:22 -03:00

58 lines
1.9 KiB
Rust

use std::fmt::Debug;
use std::sync::Arc;
use std::sync::OnceLock;
use serenity::all::UserId;
use crate::errors::DatabaseStoredError;
pub mod access;
pub mod mariadb;
pub mod postgres;
pub mod sqlite;
#[derive(Debug)]
pub enum DBKind {
Access,
SQLite,
MariaDB,
PostgreSQL,
}
static DATABASE_ACCESSOR: OnceLock<Arc<Box<dyn DatabaseAccessor>>> = OnceLock::new();
/// # Panics
/// This function will panic if used after the database has already been set
///
/// You should not worry about this as this function only ever gets called once at the start of the program and you are doing something wrong if you need to call this a second time
pub fn set_db(dba: Box<dyn DatabaseAccessor>) {
assert!(DATABASE_ACCESSOR.set(Arc::new(dba)).is_ok(), "attempted to set database accessor after init");
}
/// # Panics
/// This function will panic if used before the database has been set
///
/// You should not worry about this as this function only ever gets called after the database has been set and you are doing something wrong if you are calling this before the database is live
pub fn get_db() -> Arc<Box<dyn DatabaseAccessor>> {
#[allow(clippy::expect_used)]
DATABASE_ACCESSOR.get().expect("attempted to get database before init").clone()
}
/// This trait will provide a very high level interface to all supported databases
/// Its implementations should also sanitize all inputs regardless of what type
/// The implementation may be multithreaded/multiconnection, but for sqlite it is limited to a single thread/locked direct access to the connection via a mutex
/// If you need more performance use a different database type
pub trait DatabaseAccessor: Sync + Send {
// TODO make a db upgrade table
fn get_db_version(&self);
fn check_db_health(&self);
fn fix_db_health(&self);
fn is_dev(&self, user_id: UserId) -> bool;
fn set_dev(&self, user_id: UserId);
fn store_error(&self, err: &DatabaseStoredError);
}