Implement temp database

This commit is contained in:
fluo10 2025-05-12 20:29:46 +09:00
parent 7f8000ef42
commit 42bc1d59f7
9 changed files with 104 additions and 68 deletions

5
Cargo.lock generated
View file

@ -2266,6 +2266,7 @@ dependencies = [
"progress-pile-migration",
"sea-orm",
"serde",
"tempfile",
"thiserror 2.0.12",
"tokio",
"toml",
@ -3245,9 +3246,9 @@ dependencies = [
[[package]]
name = "tempfile"
version = "3.19.1"
version = "3.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf"
checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1"
dependencies = [
"fastrand",
"getrandom 0.3.2",

View file

@ -20,4 +20,7 @@ serde.workspace = true
thiserror.workspace = true
tokio.workspace = true
toml.workspace = true
uuid.workspace = true
uuid.workspace = true
[dev-dependencies]
tempfile = "3.20.0"

View file

@ -17,25 +17,24 @@ pub use progress_entry::{
#[cfg(test)]
mod tests {
use std::time::Duration;
use super::*;
use chrono::Local;
use progress_pile_core::global::GlobalDatabase;
use sea_orm::{entity::*, DatabaseConnection};
use sea_orm::{entity::*, ConnectOptions, Database, DatabaseConnection};
use progress_pile_migration::{ClientMigrator, MigratorTrait};
use uuid::Uuid;
use crate::error::Error;
use crate::global::database::{
GLOBAL_DATABASE,
tests::*
};
async fn get_or_try_init_test_database() -> Result<&'static DatabaseConnection, Error> {
Ok(GlobalDatabase::get_or_try_init("sqlite::memory:", ClientMigrator).await?)
}
#[tokio::test]
#[tokio::test]
async fn check_insert_entity() {
let db = get_or_try_init_test_database().await.unwrap();
let db = GLOBAL_DATABASE.get_or_init_temp().await;
let category = ProgressCategoryActiveModel{
name: Set("test_category".to_owned()),
@ -47,9 +46,5 @@ mod tests {
..ProgressEntryActiveModel::new()
}.insert(db).await.unwrap();
}
#[tokio::test]
async fn connect_database () {
let db = get_or_try_init_test_database().await.unwrap();
assert!(db.ping().await.is_ok());
}
}

View file

@ -0,0 +1,67 @@
use progress_pile_migration::{ClientMigrator, MigratorTrait};
use sea_orm::{ConnectOptions, Database, DatabaseConnection};
use crate::error::Error;
use tokio::sync::OnceCell;
use progress_pile_core::global::GlobalDatabase;
pub static GLOBAL_DATABASE: OnceGlobalDatabase = OnceGlobalDatabase{
inner: OnceCell::const_new(),
};
pub struct OnceGlobalDatabase {
inner: OnceCell<DatabaseConnection>,
}
impl OnceGlobalDatabase {
}
impl GlobalDatabase for OnceGlobalDatabase {
fn get(&self) -> Option<& DatabaseConnection> {
self.inner.get()
}
async fn get_or_try_init(&self) -> Result<&DatabaseConnection, Error> {
todo!()
}
async fn get_or_try_init_with_connect_options<T>(&self, options: T) -> Result<&DatabaseConnection, Error> where
T: Into<ConnectOptions>,
{
Ok(self.inner.get_or_try_init(|| async {
let db = Database::connect(options).await?;
ClientMigrator::up(&db, None).await?;
Ok::<DatabaseConnection, Error>(db)
}).await?)
}
}
#[cfg(test)]
pub mod tests {
use std::sync::LazyLock;
use tokio::sync::OnceCell;
use super::*;
pub static TEST_DATABASE_URL: LazyLock<String> = LazyLock::new(|| {
let mut temp_path = tempfile::NamedTempFile::new().unwrap().into_temp_path();
temp_path.disable_cleanup(true);
let url = "sqlite://".to_string() + temp_path.as_os_str().to_str().unwrap() + "?mode=rwc";
println!("{}", &url);
url
});
impl OnceGlobalDatabase {
pub async fn get_or_init_temp(&self) -> &DatabaseConnection {
self.get_or_try_init_with_connect_options(&*TEST_DATABASE_URL).await.unwrap()
}
}
#[tokio::test]
async fn connect_database () {
let db = GLOBAL_DATABASE.get_or_init_temp().await;
assert!(db.ping().await.is_ok());
}
}

View file

@ -0,0 +1 @@
pub mod database;

View file

@ -1,6 +1,7 @@
pub mod auth;
pub mod config;
pub mod entity;
pub mod global;
pub use progress_pile_core::{
error,

View file

@ -0,0 +1,10 @@
use chrono_tz::Tz;
use crate::{config::DatabaseConfig, error::Error};
pub trait GlobalConfigTrait<T> {
fn get(&self) -> Option<T>;
fn get_or_try_init(&self) -> Result<T, Error>;
fn get_database_config(&self) -> Option<DatabaseConfig>;
fn get_time_zone(&self) -> Option<Tz>;
}

View file

@ -1,60 +1,17 @@
use crate::error::Error;
use sea_orm::{ConnectOptions, Database, DatabaseConnection};
use sea_orm::{ConnectOptions, Database, DatabaseConnection, DbErr};
use sea_orm_migration::MigratorTrait;
use tokio::sync::OnceCell;
/*
pub struct OnceDatabaseConnection {
inner: OnceCell<DatabaseConnection>,
}
impl OnceDatabaseConnection {
const fn new() -> Self {
Self {
inner: OnceCell::const_new(),
}
}
pub fn get(&self) -> Option<&DatabaseConnection> {
self.inner.get()
}
pub async fn get_or_try_init<T, U>(&self, options: T, _: U) -> Result<&DatabaseConnection, Error> where
T: Into<ConnectOptions>,
U: MigratorTrait
{
self.inner.get_or_try_init(|| async {
let db = Database::connect(options).await?;
U::up(&db, None).await?;
Ok(db)
}).await
}
}
pub static DATABASE_CONNECTION: OnceDatabaseConnection = OnceDatabaseConnection::new();
*/
pub static DATABASE_CONNECTION: OnceCell<DatabaseConnection> = OnceCell::const_new();
pub struct GlobalDatabase;
impl GlobalDatabase {
pub fn get() -> Option<&'static DatabaseConnection> {
DATABASE_CONNECTION.get()
}
pub async fn get_or_try_init<T, U>(options: T, _: U) -> Result<&'static DatabaseConnection, Error> where
T: Into<ConnectOptions>,
U: MigratorTrait
{
DATABASE_CONNECTION.get_or_try_init(|| async {
let db = Database::connect(options).await?;
U::up(&db, None).await?;
Ok(db)
}).await
}
pub trait GlobalDatabase {
fn get(&self) -> Option<&DatabaseConnection>;
async fn get_or_try_init(&self) -> Result<&DatabaseConnection, Error>;
async fn get_or_try_init_with_connect_options<T>(&self, options: T) -> Result<&DatabaseConnection, Error> where
T: Into<ConnectOptions>;
}
#[cfg(test)]

View file

@ -1,4 +1,5 @@
pub mod config;
mod database;
pub use database::GlobalDatabase;
pub use database::GlobalDatabase;
pub use database::DATABASE_CONNECTION;