From d94a92746114c579561c983c69d3fb6b2a2e2343 Mon Sep 17 00:00:00 2001 From: fluo10 Date: Tue, 10 Jun 2025 07:47:37 +0900 Subject: [PATCH] Add cache database migration --- Cargo.toml | 1 - examples/simple-list/Cargo.toml | 1 - lazy-supplements-migration/Cargo.toml | 9 -- lazy-supplements-migration/README.md | 41 ------- lazy-supplements-migration/src/lib.rs | 18 --- lazy-supplements-migration/src/main.rs | 6 - lazy-supplements/Cargo.toml | 4 +- lazy-supplements/src/entity/node.rs | 2 +- .../src/entity/record_deletion.rs | 4 +- lazy-supplements/src/global/database.rs | 80 ++++++------- lazy-supplements/src/global/mod.rs | 85 ++++++++++++-- lazy-supplements/src/lib.rs | 1 + .../m20220101_000001_create_cache_tables.rs | 110 ++++++++++++++++++ lazy-supplements/src/migration/cache/mod.rs | 12 ++ .../m20220101_000001_create_main_tables.rs | 2 +- lazy-supplements/src/migration/main/mod.rs | 14 +++ lazy-supplements/src/migration/mod.rs | 10 ++ 17 files changed, 267 insertions(+), 133 deletions(-) delete mode 100644 lazy-supplements-migration/Cargo.toml delete mode 100644 lazy-supplements-migration/README.md delete mode 100644 lazy-supplements-migration/src/lib.rs delete mode 100644 lazy-supplements-migration/src/main.rs create mode 100644 lazy-supplements/src/migration/cache/m20220101_000001_create_cache_tables.rs create mode 100644 lazy-supplements/src/migration/cache/mod.rs rename lazy-supplements-migration/src/m20220101_000001_create_lazy_supplements_tables.rs => lazy-supplements/src/migration/main/m20220101_000001_create_main_tables.rs (98%) create mode 100644 lazy-supplements/src/migration/main/mod.rs create mode 100644 lazy-supplements/src/migration/mod.rs diff --git a/Cargo.toml b/Cargo.toml index ec4ea5e..8f88989 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,6 @@ repository = "https://forgejo.fireturlte.net" [workspace.dependencies] lazy-supplements.path = "lazy-supplements" -lazy-supplements-migration.path = "lazy-supplements-migration" libp2p = { version = "0.55.0", features = ["macros", "mdns", "noise", "ping", "tcp", "tokio", "yamux" ] } [workspace.dependencies.sea-orm-migration] diff --git a/examples/simple-list/Cargo.toml b/examples/simple-list/Cargo.toml index 8e9c691..423d81e 100644 --- a/examples/simple-list/Cargo.toml +++ b/examples/simple-list/Cargo.toml @@ -10,7 +10,6 @@ repository.workspace = true chrono = "0.4.41" clap = { version = "4.5.38", features = ["derive"] } lazy-supplements.workspace = true -lazy-supplements-migration.workspace = true sea-orm = "1.1.11" sea-orm-migration.workspace = true serde = { version = "1.0.219", features = ["derive"] } diff --git a/lazy-supplements-migration/Cargo.toml b/lazy-supplements-migration/Cargo.toml deleted file mode 100644 index 4a22b40..0000000 --- a/lazy-supplements-migration/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "lazy-supplements-migration" -version = "0.1.0" -edition = "2021" -publish = false - -[dependencies] -async-std = { version = "1", features = ["attributes", "tokio1"] } -sea-orm-migration.workspace = true diff --git a/lazy-supplements-migration/README.md b/lazy-supplements-migration/README.md deleted file mode 100644 index 3b438d8..0000000 --- a/lazy-supplements-migration/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# Running Migrator CLI - -- Generate a new migration file - ```sh - cargo run -- generate MIGRATION_NAME - ``` -- Apply all pending migrations - ```sh - cargo run - ``` - ```sh - cargo run -- up - ``` -- Apply first 10 pending migrations - ```sh - cargo run -- up -n 10 - ``` -- Rollback last applied migrations - ```sh - cargo run -- down - ``` -- Rollback last 10 applied migrations - ```sh - cargo run -- down -n 10 - ``` -- Drop all tables from the database, then reapply all migrations - ```sh - cargo run -- fresh - ``` -- Rollback all applied migrations, then reapply all migrations - ```sh - cargo run -- refresh - ``` -- Rollback all applied migrations - ```sh - cargo run -- reset - ``` -- Check the status of all migrations - ```sh - cargo run -- status - ``` diff --git a/lazy-supplements-migration/src/lib.rs b/lazy-supplements-migration/src/lib.rs deleted file mode 100644 index 13606f6..0000000 --- a/lazy-supplements-migration/src/lib.rs +++ /dev/null @@ -1,18 +0,0 @@ -use sea_orm_migration::{prelude::*, schema::*}; - -pub mod m20220101_000001_create_lazy_supplements_tables; - -pub struct Migrator; - -#[async_trait::async_trait] -pub trait TableMigration { - async fn up<'a>(manager: &'a SchemaManager<'a>) -> Result<(), DbErr> ; - async fn down<'a>(manager: &'a SchemaManager<'a>) -> Result<(), DbErr>; -} - -#[async_trait::async_trait] -impl MigratorTrait for Migrator { - fn migrations() -> Vec> { - vec![Box::new(m20220101_000001_create_lazy_supplements_tables::Migration)] - } -} diff --git a/lazy-supplements-migration/src/main.rs b/lazy-supplements-migration/src/main.rs deleted file mode 100644 index 03983ba..0000000 --- a/lazy-supplements-migration/src/main.rs +++ /dev/null @@ -1,6 +0,0 @@ -use sea_orm_migration::prelude::*; - -#[async_std::main] -async fn main() { - cli::run_cli(lazy_supplements_migration::Migrator).await; -} diff --git a/lazy-supplements/Cargo.toml b/lazy-supplements/Cargo.toml index 5729b22..463b031 100644 --- a/lazy-supplements/Cargo.toml +++ b/lazy-supplements/Cargo.toml @@ -25,13 +25,11 @@ serde = { version = "1.0.219", features = ["derive"] } shell-words = "1.1.0" tempfile = { version = "3.20.0", optional = true } thiserror = "2.0.12" -tokio = { version = "1.45.0", features = ["macros", "rt"] } +tokio = { version = "1.45.0", features = ["macros", "rt", "rt-multi-thread"] } toml = "0.8.22" tracing = "0.1.41" tracing-subscriber = { version = "0.3.19", features = ["env-filter"] } uuid = { version = "1.17.0", features = ["v4"] } [dev-dependencies] -lazy-supplements-migration.workspace = true -sea-orm-migration.workspace = true tempfile = "3.20.0" diff --git a/lazy-supplements/src/entity/node.rs b/lazy-supplements/src/entity/node.rs index 464b46b..5866811 100644 --- a/lazy-supplements/src/entity/node.rs +++ b/lazy-supplements/src/entity/node.rs @@ -49,7 +49,7 @@ mod tests { #[tokio::test] async fn check_insert_node() { - let db = crate::global::get_or_init_temporary_database().await; + let db = crate::global::get_or_init_temporary_main_database().await; ActiveModel{ peer_id: Set(identity::Keypair::generate_ed25519().public().to_peer_id().to_string()), diff --git a/lazy-supplements/src/entity/record_deletion.rs b/lazy-supplements/src/entity/record_deletion.rs index c739dd2..6077afb 100644 --- a/lazy-supplements/src/entity/record_deletion.rs +++ b/lazy-supplements/src/entity/record_deletion.rs @@ -38,11 +38,11 @@ mod tests { use super::*; use uuid::Uuid; - use crate::global::get_or_init_temporary_database; + use crate::global::get_or_init_temporary_main_database; #[tokio::test] async fn check_insert_record_deletion() { - let db = get_or_init_temporary_database().await; + let db = get_or_init_temporary_main_database().await; assert!(ActiveModel{ table_name: Set("test_table".to_string()), diff --git a/lazy-supplements/src/global/database.rs b/lazy-supplements/src/global/database.rs index 86e8a10..06873af 100644 --- a/lazy-supplements/src/global/database.rs +++ b/lazy-supplements/src/global/database.rs @@ -8,61 +8,57 @@ use tokio::sync::OnceCell; use super::Global; #[cfg(any(test, feature="test"))] -pub static TEST_DATABASE_URL: std::sync::LazyLock = std::sync::LazyLock::new(|| { +pub static TEST_MAIN_DATABASE_URL: std::sync::LazyLock = std::sync::LazyLock::new(|| { + let mut temp_path = tempfile::NamedTempFile::new().unwrap().into_temp_path(); + temp_path.disable_cleanup(true); + println!("{}", temp_path.as_os_str().to_str().unwrap()); + temp_path +}); +#[cfg(any(test, feature="test"))] +pub static TEST_CACHE_DATABASE_URL: std::sync::LazyLock = std::sync::LazyLock::new(|| { let mut temp_path = tempfile::NamedTempFile::new().unwrap().into_temp_path(); temp_path.disable_cleanup(true); println!("{}", temp_path.as_os_str().to_str().unwrap()); temp_path }); -impl Global { - fn get_database(&self) -> Option<&DatabaseConnection> { - self.database.get() - } - async fn get_or_try_init_database(&self, path: T, _: U) -> Result<&DatabaseConnection, Error> +pub trait GlobalDatabase { + fn get_main_database(&self) -> Option<&DatabaseConnection>; + async fn get_or_try_init_main_database(&self, path: T, _: U) -> Result<&DatabaseConnection, Error> where T: AsRef, - U: MigratorTrait, - { - let url = "sqlite://".to_string() + path.as_ref().to_str().unwrap() + "?mode=rwc"; - - Ok(self.database.get_or_try_init(|| async { - let db = Database::connect(&url).await?; - U::up(&db, None).await?; - Ok::(db) - }).await?) + U: MigratorTrait + ; + fn get_unwrapped_main_database(&self) -> &DatabaseConnection { + match self.get_main_database() { + Some(x) => x, + None => unreachable!("Error: global main database is not initialized!") + } + } + fn get_cache_database(&self) -> Option<&DatabaseConnection>; + async fn get_or_try_init_cache_database(&self, path: T, _: U) -> Result<&DatabaseConnection, Error> + where + T: AsRef, + U: MigratorTrait + ; + fn get_unwrapped_cache_database(&self) -> &DatabaseConnection { + match self.get_cache_database() { + Some(x) => x, + None => unreachable!("Error: global main database is not initialized!") + } } #[cfg(any(test, feature="test"))] - pub async fn get_or_try_init_temporary_database(&self, migrator: T) -> Result<&DatabaseConnection, Error> + async fn get_or_try_init_temporary_main_database(&self, migrator: T) -> Result<&DatabaseConnection, Error> where T: MigratorTrait, { - self.get_or_try_init_database(&*TEST_DATABASE_URL, migrator).await + self.get_or_try_init_main_database(&*TEST_MAIN_DATABASE_URL, migrator).await } -} - - - - -#[cfg(test)] -pub mod tests { - use std::sync::LazyLock; - - use lazy_supplements_migration::Migrator; - use sea_orm_migration::MigratorTrait; - - use crate::global::GLOBAL; - - use super::*; - - pub async fn get_or_init_temporary_database() -> &'static DatabaseConnection { - GLOBAL.get_or_try_init_temporary_database( Migrator).await.unwrap() + #[cfg(any(test, feature="test"))] + async fn get_or_try_init_temporary_cache_database(&self, migrator: T) -> Result<&DatabaseConnection, Error> + where + T: MigratorTrait, + { + self.get_or_try_init_cache_database(&*TEST_CACHE_DATABASE_URL, migrator).await } - - #[tokio::test] - async fn connect_database () { - let db = get_or_init_temporary_database().await; - assert!(db.ping().await.is_ok()); - } - } \ No newline at end of file diff --git a/lazy-supplements/src/global/mod.rs b/lazy-supplements/src/global/mod.rs index fb16691..7b18a4f 100644 --- a/lazy-supplements/src/global/mod.rs +++ b/lazy-supplements/src/global/mod.rs @@ -1,12 +1,14 @@ -use std::{collections::HashMap, net::{IpAddr, Ipv4Addr}, path::PathBuf, sync::LazyLock}; +use std::{collections::HashMap, net::{IpAddr, Ipv4Addr}, path::{Path, PathBuf}, sync::LazyLock}; use crate::{config::{NodeConfig, RawNodeConfig}, error::Error}; use futures::StreamExt; use libp2p::{swarm::SwarmEvent, Multiaddr, PeerId}; -use sea_orm::DatabaseConnection; +use sea_orm::{prelude::*, Database}; +use sea_orm_migration::MigratorTrait; use tokio::sync::{OnceCell, RwLock}; mod database; +use database::GlobalDatabase; pub static PRODUCT_NAME: LazyLock = LazyLock::new(|| { env!("CARGO_PKG_NAME").to_string() @@ -54,18 +56,18 @@ pub static DEFAULT_DATABASE_FILE_PATH: LazyLock = LazyLock::new(|| { pub static GLOBAL: Global = Global{ node_config: OnceCell::const_new(), - database: OnceCell::const_new(), + main_database: OnceCell::const_new(), + cache_database: OnceCell::const_new(), peers: OnceCell::const_new(), + }; pub struct Global { pub node_config: OnceCell, - pub database: OnceCell, + pub main_database: OnceCell, + pub cache_database: OnceCell, pub peers: OnceCell>>, } -#[cfg(test)] -pub use database::tests::get_or_init_temporary_database; - impl Global { pub fn get_node_config(&self) -> Option<&NodeConfig> { self.node_config.get() @@ -102,6 +104,42 @@ impl Global { } } +impl GlobalDatabase for Global { + fn get_main_database(&self) -> Option<&DatabaseConnection> { + self.main_database.get() + } + async fn get_or_try_init_main_database(&self, path: T, _: U) -> Result<&DatabaseConnection, Error> + where + T: AsRef, + U: MigratorTrait, + { + let url = "sqlite://".to_string() + path.as_ref().to_str().unwrap() + "?mode=rwc"; + + Ok(self.main_database.get_or_try_init(|| async { + let db = Database::connect(&url).await?; + U::up(&db, None).await?; + Ok::(db) + }).await?) + } + fn get_cache_database(&self) -> Option<&DatabaseConnection> { + self.cache_database.get() + } + async fn get_or_try_init_cache_database(&self, path: T, _: U) -> Result<&DatabaseConnection, Error> + where + T: AsRef, + U: MigratorTrait, + { + let url = "sqlite://".to_string() + path.as_ref().to_str().unwrap() + "?mode=rwc"; + + Ok(self.cache_database.get_or_try_init(|| async { + let db = Database::connect(&url).await?; + U::up(&db, None).await?; + Ok::(db) + }).await?) + } + +} + pub static DEFAULT_RAW_NODE_CONFIG: LazyLock = LazyLock::new(|| { RawNodeConfig { secret: None, @@ -109,4 +147,35 @@ pub static DEFAULT_RAW_NODE_CONFIG: LazyLock = LazyLock::new(|| { listen_ips: Some(DEFAULT_LISTEN_IPS.to_vec()), port: Some(DEFAULT_PORT), } -}); \ No newline at end of file +}); +#[cfg(test)] +pub use tests::{get_or_init_temporary_main_database, get_or_init_temporary_cache_database}; +#[cfg(test)] +pub mod tests { + use std::sync::LazyLock; + + use sea_orm_migration::MigratorTrait; + + use crate::{global::GLOBAL, migration::{cache::CacheMigrator, main::MainMigrator}}; + + use super::*; + + pub async fn get_or_init_temporary_main_database() -> &'static DatabaseConnection { + GLOBAL.get_or_try_init_temporary_main_database(MainMigrator).await.unwrap() + } + pub async fn get_or_init_temporary_cache_database() -> &'static DatabaseConnection { + GLOBAL.get_or_try_init_temporary_cache_database(CacheMigrator).await.unwrap() + } + + #[tokio::test] + async fn connect_main_database () { + let db = get_or_init_temporary_main_database().await; + assert!(db.ping().await.is_ok()); + } + + #[tokio::test] + async fn connect_cache_database () { + let db = get_or_init_temporary_cache_database().await; + assert!(db.ping().await.is_ok()); + } +} \ No newline at end of file diff --git a/lazy-supplements/src/lib.rs b/lazy-supplements/src/lib.rs index 5c5f70a..db839e6 100644 --- a/lazy-supplements/src/lib.rs +++ b/lazy-supplements/src/lib.rs @@ -3,6 +3,7 @@ pub mod config; pub mod entity; pub mod error; pub mod global; +pub mod migration; pub mod p2p; #[cfg(any(test, feature="test"))] pub mod tests; diff --git a/lazy-supplements/src/migration/cache/m20220101_000001_create_cache_tables.rs b/lazy-supplements/src/migration/cache/m20220101_000001_create_cache_tables.rs new file mode 100644 index 0000000..cb19cc2 --- /dev/null +++ b/lazy-supplements/src/migration/cache/m20220101_000001_create_cache_tables.rs @@ -0,0 +1,110 @@ +use sea_orm_migration::{prelude::*, schema::*}; + +use crate::migration::TableMigration; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + Peer::up(manager).await?; + Address::up(manager).await?; + Ok(()) + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + Peer::down(manager).await?; + Address::down(manager).await?; + Ok(()) + } +} + +#[derive(DeriveIden)] +enum Peer { + Table, + Id, + PeerId, + CreatedAt, + UpdatedAt, + ExpiresAt, +} + +static IDX_PEER_PEER_ID: &str = "idx_peer_peer_id"; + +#[async_trait::async_trait] +impl TableMigration for Peer { + async fn up<'a>(manager: &'a SchemaManager<'a>) -> Result<(), DbErr> { + manager.create_table( + Table::create() + .table(Self::Table) + .if_not_exists() + .col(pk_auto(Self::Id)) + .col(timestamp(Self::CreatedAt)) + .col(timestamp(Self::UpdatedAt)) + .col(timestamp(Self::ExpiresAt)) + .col(string_len_uniq(Self::PeerId, 255)) + .to_owned() + ).await?; + manager.create_index( + Index::create() + .name(IDX_PEER_PEER_ID) + .table(Self::Table) + .col(Self::PeerId) + .to_owned() + ).await?; + Ok(()) + } + async fn down<'a>(manager: &'a SchemaManager<'a>) -> Result<(), DbErr>{ + manager.drop_table(Table::drop().table(Self::Table).to_owned()).await + } +} + +#[derive(DeriveIden, DeriveMigrationName)] +enum Address { + Table, + Id, + PeerId, + CreatedAt, + UpdatedAt, + ExpiresAt, + MultiAddress, +} + +static IDX_ADDRESS_MULTIADDRESS: &str = "idx_address_multiaddress"; +static FK_ADDRESS_PEER: &str = "fk_address_peer"; + +#[async_trait::async_trait] +impl TableMigration for Address { + async fn up<'a>(manager: &'a SchemaManager<'a>) -> Result<(), DbErr> { + manager.create_table( + Table::create() + .table(Self::Table) + .if_not_exists() + .col(pk_auto(Self::Id)) + .col(integer(Self::PeerId)) + .col(timestamp(Self::CreatedAt)) + .col(timestamp(Self::UpdatedAt)) + .col(timestamp(Self::ExpiresAt)) + .col(text_uniq(Self::MultiAddress)) + .foreign_key( + ForeignKey::create() + .name(FK_ADDRESS_PEER) + .from(Self::Table, Self::PeerId) + .to(Peer::Table, Peer::Id) + ) + .to_owned() + ).await?; + manager.create_index( + Index::create() + .name(IDX_ADDRESS_MULTIADDRESS) + .table(Self::Table) + .col(Self::MultiAddress) + .to_owned() + ).await?; + Ok(()) + } + async fn down<'a>(manager: &'a SchemaManager<'a>) -> Result<(), DbErr>{ + manager.drop_table(Table::drop().table(Self::Table).to_owned()).await + } +} \ No newline at end of file diff --git a/lazy-supplements/src/migration/cache/mod.rs b/lazy-supplements/src/migration/cache/mod.rs new file mode 100644 index 0000000..87f27fd --- /dev/null +++ b/lazy-supplements/src/migration/cache/mod.rs @@ -0,0 +1,12 @@ +use sea_orm_migration::prelude::*; + +pub mod m20220101_000001_create_cache_tables; + +pub struct CacheMigrator; + +#[async_trait::async_trait] +impl MigratorTrait for CacheMigrator { + fn migrations() -> Vec> { + vec![Box::new(m20220101_000001_create_cache_tables::Migration)] + } +} diff --git a/lazy-supplements-migration/src/m20220101_000001_create_lazy_supplements_tables.rs b/lazy-supplements/src/migration/main/m20220101_000001_create_main_tables.rs similarity index 98% rename from lazy-supplements-migration/src/m20220101_000001_create_lazy_supplements_tables.rs rename to lazy-supplements/src/migration/main/m20220101_000001_create_main_tables.rs index 88794c8..c69bfbe 100644 --- a/lazy-supplements-migration/src/m20220101_000001_create_lazy_supplements_tables.rs +++ b/lazy-supplements/src/migration/main/m20220101_000001_create_main_tables.rs @@ -1,6 +1,6 @@ use sea_orm_migration::{prelude::*, schema::*}; -use crate::TableMigration; +use crate::migration::TableMigration; #[derive(DeriveMigrationName)] pub struct Migration; diff --git a/lazy-supplements/src/migration/main/mod.rs b/lazy-supplements/src/migration/main/mod.rs new file mode 100644 index 0000000..3089688 --- /dev/null +++ b/lazy-supplements/src/migration/main/mod.rs @@ -0,0 +1,14 @@ +use sea_orm_migration::prelude::*; + +pub mod m20220101_000001_create_main_tables; + +#[cfg(any(test, feature="test"))] +pub struct MainMigrator; + +#[cfg(any(test, feature="test"))] +#[async_trait::async_trait] +impl MigratorTrait for MainMigrator { + fn migrations() -> Vec> { + vec![Box::new(m20220101_000001_create_main_tables::Migration)] + } +} diff --git a/lazy-supplements/src/migration/mod.rs b/lazy-supplements/src/migration/mod.rs new file mode 100644 index 0000000..74e8a1f --- /dev/null +++ b/lazy-supplements/src/migration/mod.rs @@ -0,0 +1,10 @@ +pub mod cache; +pub mod main; + +use sea_orm_migration::{prelude::*, schema::*}; + +#[async_trait::async_trait] +pub trait TableMigration { + async fn up<'a>(manager: &'a SchemaManager<'a>) -> Result<(), DbErr> ; + async fn down<'a>(manager: &'a SchemaManager<'a>) -> Result<(), DbErr>; +} \ No newline at end of file