caretta-sync/core/src/global/database_connection.rs

83 lines
2.7 KiB
Rust
Raw Normal View History

2025-08-20 06:50:35 +09:00
use std::path::{Path, PathBuf};
2025-06-19 07:24:44 +09:00
use sea_orm::{ConnectOptions, Database, DbErr, DatabaseConnection};
use sea_orm_migration::MigratorTrait;
2025-08-20 06:50:35 +09:00
use crate::{config::StorageConfig, error::Error};
2025-06-19 07:24:44 +09:00
use tokio::sync::OnceCell;
2025-08-20 06:50:35 +09:00
enum StorageType {
Data,
Cache,
}
impl std::fmt::Display for StorageType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f,"{}", match self {
StorageType::Data => "data",
StorageType::Cache => "cache",
});
Ok(())
}
}
pub static DATA_DATABASE_CONNECTION: GlobalDatabaseConnection = GlobalDatabaseConnection::const_new(StorageType::Data);
pub static CACHE_DATABASE_CONNECTION: GlobalDatabaseConnection = GlobalDatabaseConnection::const_new(StorageType::Cache);
2025-06-19 07:24:44 +09:00
2025-06-22 11:29:44 +09:00
pub struct GlobalDatabaseConnection {
2025-08-20 06:50:35 +09:00
storage: StorageType,
2025-06-20 08:42:02 +09:00
inner: OnceCell<DatabaseConnection>
2025-06-20 07:28:51 +09:00
}
2025-06-19 07:24:44 +09:00
2025-06-20 08:42:02 +09:00
impl GlobalDatabaseConnection {
2025-08-20 06:50:35 +09:00
pub const fn const_new(storage: StorageType) -> Self {
2025-06-20 08:42:02 +09:00
Self {
2025-08-20 06:50:35 +09:00
storage: storage,
2025-06-20 08:42:02 +09:00
inner: OnceCell::const_new()
}
}
2025-08-20 06:50:35 +09:00
pub fn get(&'static self) -> Option<&'static DatabaseConnection> {
self.inner.get()
}
fn get_file_path<T>(&self, config: T) -> PathBuf
where
T: AsRef<StorageConfig>
{
match self.storage {
StorageType::Cache => config.as_ref().cache_directory.join("cache.db"),
StorageType::Data => config.as_ref().data_directory.join("data.db"),
}
}
pub fn get_unchecked(&'static self) -> &'static DatabaseConnection {
self.get().expect("Global database connection should initialized beforehand!")
2025-06-20 08:42:02 +09:00
}
2025-08-20 06:50:35 +09:00
pub async fn get_or_try_init<T, U>(&'static self, config: T, _: U) -> Result<&'static DatabaseConnection, Error>
2025-06-20 08:42:02 +09:00
where
2025-08-20 06:50:35 +09:00
T: AsRef<StorageConfig>,
2025-06-20 08:42:02 +09:00
U: MigratorTrait
{
2025-08-20 06:50:35 +09:00
let url = "sqlite://".to_string() + &self.get_file_path(config).into_os_string().into_string()? + "?mode=rwc";
Ok(self.inner.get_or_try_init(|| async {
2025-06-20 08:42:02 +09:00
let db = Database::connect(&url).await?;
U::up(&db, None).await?;
Ok::<DatabaseConnection, DbErr>(db)
2025-08-20 06:50:35 +09:00
}).await?)
2025-06-20 08:42:02 +09:00
}
2025-06-20 07:28:51 +09:00
}
2025-06-22 11:29:44 +09:00
#[cfg(test)]
pub use tests::*;
#[cfg(test)]
mod tests {
use super::*;
2025-08-20 06:50:35 +09:00
use crate::{cache::migration::CacheMigrator, data::migration::DataMigrator, global::CONFIG, tests::{TEST_CONFIG}};
2025-06-22 11:29:44 +09:00
pub async fn get_or_init_test_data_database() -> &'static DatabaseConnection{
2025-08-20 06:50:35 +09:00
DATA_DATABASE_CONNECTION.get_or_try_init(&*TEST_CONFIG, DataMigrator).await.unwrap()
2025-06-22 11:29:44 +09:00
}
pub async fn get_or_init_test_cache_database() -> &'static DatabaseConnection{
2025-08-20 06:50:35 +09:00
CACHE_DATABASE_CONNECTION.get_or_try_init(&*TEST_CONFIG, CacheMigrator).await.unwrap()
2025-06-22 11:29:44 +09:00
}
}