From 8fbf8a16ec893c07a60400c34c671387a8a34087 Mon Sep 17 00:00:00 2001 From: fluo10 Date: Tue, 24 Jun 2025 22:06:25 +0900 Subject: [PATCH] Add wrapper value for Multiaddr and PeerId --- lazy-supplements-core/src/cache/entity/mod.rs | 8 -- .../src/cache/entity/multi_address.rs | 61 ---------------- .../src/cache/entity/peer.rs | 51 ++++++++----- .../m20220101_000001_create_cache_tables.rs | 73 +++++++------------ lazy-supplements-core/src/config/storage.rs | 8 +- lazy-supplements-core/src/data/mod.rs | 3 +- lazy-supplements-core/src/data/value/mod.rs | 5 ++ .../src/data/value/multiaddr.rs | 68 +++++++++++++++++ .../src/data/value/peer_id.rs | 68 +++++++++++++++++ lazy-supplements-core/src/p2p/mod.rs | 6 +- lazy-supplements-core/src/tests.rs | 4 +- 11 files changed, 216 insertions(+), 139 deletions(-) delete mode 100644 lazy-supplements-core/src/cache/entity/multi_address.rs create mode 100644 lazy-supplements-core/src/data/value/mod.rs create mode 100644 lazy-supplements-core/src/data/value/multiaddr.rs create mode 100644 lazy-supplements-core/src/data/value/peer_id.rs diff --git a/lazy-supplements-core/src/cache/entity/mod.rs b/lazy-supplements-core/src/cache/entity/mod.rs index a75f9bf..2112d45 100644 --- a/lazy-supplements-core/src/cache/entity/mod.rs +++ b/lazy-supplements-core/src/cache/entity/mod.rs @@ -1,13 +1,5 @@ -mod multi_address; mod peer; -pub use multi_address::{ - ActiveModel as ActiveMultiAddressModel, - Column as MultiAddressColumn, - Model as MultiAddressModel, - Entity as MultiAddressEntity, -}; - pub use peer::{ ActiveModel as ActivePeerModel, Column as PeerColumn, diff --git a/lazy-supplements-core/src/cache/entity/multi_address.rs b/lazy-supplements-core/src/cache/entity/multi_address.rs deleted file mode 100644 index 8eff6d6..0000000 --- a/lazy-supplements-core/src/cache/entity/multi_address.rs +++ /dev/null @@ -1,61 +0,0 @@ -use chrono::Local; -use sea_orm::entity::{ - *, - prelude::* -}; -use serde::{Deserialize, Serialize}; - - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)] -#[sea_orm(table_name = "node")] -pub struct Model { - #[sea_orm(primary_key)] - pub id: u32, - #[sea_orm(indexed)] - pub created_at: DateTimeUtc, - #[sea_orm(indexed)] - pub updated_at: DateTimeUtc, - #[sea_orm(indexed)] - pub synced_at: Option, - #[sea_orm(indexed)] - pub peer_id: String, - #[sea_orm(column_type = "Text")] - pub note: String, -} - -#[derive(Copy, Clone, Debug, DeriveRelation, EnumIter)] -pub enum Relation {} - -impl ActiveModelBehavior for ActiveModel {} - -impl ActiveModel { - pub fn new() -> Self { - let timestamp: DateTimeUtc = Local::now().to_utc(); - Self{ - created_at: Set(timestamp), - updated_at: Set(timestamp), - ..Default::default() - } - } -} - -#[cfg(test)] -mod tests { - use crate::global::get_or_init_test_cache_database; - - use super::*; - - use libp2p::identity; - - #[tokio::test] - async fn check_insert_node() { - let db = get_or_init_test_cache_database().await; - - ActiveModel{ - peer_id: Set(identity::Keypair::generate_ed25519().public().to_peer_id().to_string()), - note: Set("test note".to_owned()), - ..ActiveModel::new() - }.insert(db).await.unwrap(); - } - -} \ No newline at end of file diff --git a/lazy-supplements-core/src/cache/entity/peer.rs b/lazy-supplements-core/src/cache/entity/peer.rs index cd3aeee..22d8dc3 100644 --- a/lazy-supplements-core/src/cache/entity/peer.rs +++ b/lazy-supplements-core/src/cache/entity/peer.rs @@ -1,13 +1,17 @@ -use chrono::Local; -use sea_orm::entity::{ - *, - prelude::* -}; +use std::str::FromStr; + +use chrono::{Days, Local}; +use libp2p::{multiaddr, Multiaddr, PeerId}; +use sea_orm::{entity::{ + prelude::*, * +}, sea_query}; use serde::{Deserialize, Serialize}; +use crate::data::value::{MultiaddrValue, PeerIdValue}; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)] -#[sea_orm(table_name = "node")] + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "peer")] pub struct Model { #[sea_orm(primary_key)] pub id: u32, @@ -16,20 +20,28 @@ pub struct Model { #[sea_orm(indexed)] pub updated_at: DateTimeUtc, #[sea_orm(indexed)] - pub peer_id: String, + pub expires_at: DateTimeUtc, + #[sea_orm(indexed)] + pub peer_id: PeerIdValue, + #[sea_orm(indexed)] + pub address: MultiaddrValue, } + #[derive(Copy, Clone, Debug, DeriveRelation, EnumIter)] pub enum Relation {} impl ActiveModelBehavior for ActiveModel {} impl ActiveModel { - pub fn new() -> Self { + pub fn new(peer_id: PeerId, multiaddr: Multiaddr) -> Self { let timestamp: DateTimeUtc = Local::now().to_utc(); Self{ + peer_id: Set(PeerIdValue::from(peer_id)), + address: Set(MultiaddrValue::from(multiaddr)), created_at: Set(timestamp), updated_at: Set(timestamp), + expires_at: Set(timestamp.checked_add_days(Days::new(30)).unwrap()), ..Default::default() } } @@ -37,20 +49,25 @@ impl ActiveModel { #[cfg(test)] mod tests { - use crate::global::get_or_init_test_cache_database; + use std::net::Ipv4Addr; + + use crate::{cache::entity::peer, global::get_or_init_test_cache_database}; use super::*; - use libp2p::identity; + use libp2p::{identity::{self, Keypair}, swarm::handler::multi}; #[tokio::test] - async fn check_insert_node() { + async fn insert() { let db = get_or_init_test_cache_database().await; - - ActiveModel{ - peer_id: Set(identity::Keypair::generate_ed25519().public().to_peer_id().to_string()), - ..ActiveModel::new() - }.insert(db).await.unwrap(); + let peer_id = Keypair::generate_ed25519().public().to_peer_id(); + let multiaddr = Multiaddr::empty() + .with(Ipv4Addr::new(127,0,0,1).into()) + .with(multiaddr::Protocol::Tcp(0)); + let inserted: Model = ActiveModel::new(peer_id.clone(), multiaddr.clone()) + .insert(db).await.unwrap(); + assert_eq!(PeerId::from(inserted.peer_id), peer_id); + assert_eq!(Multiaddr::from(inserted.address), multiaddr); } } \ No newline at end of file diff --git a/lazy-supplements-core/src/cache/migration/m20220101_000001_create_cache_tables.rs b/lazy-supplements-core/src/cache/migration/m20220101_000001_create_cache_tables.rs index cb19cc2..4ffd418 100644 --- a/lazy-supplements-core/src/cache/migration/m20220101_000001_create_cache_tables.rs +++ b/lazy-supplements-core/src/cache/migration/m20220101_000001_create_cache_tables.rs @@ -9,18 +9,16 @@ pub struct Migration; 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)] +#[derive(DeriveIden, DeriveMigrationName)] enum Peer { Table, Id, @@ -28,9 +26,14 @@ enum Peer { CreatedAt, UpdatedAt, ExpiresAt, + Address, } +static IDX_PEER_ADDRESS: &str = "idx_peer_address"; static IDX_PEER_PEER_ID: &str = "idx_peer_peer_id"; +static IDX_PEER_CREATED_AT: &str = "idx_peer_created_at"; +static IDX_PEER_UPDATED_AT: &str = "idx_peer_updated_at"; +static IDX_PEER_EXPIRES_AT: &str = "idx_peer_expires_at"; #[async_trait::async_trait] impl TableMigration for Peer { @@ -40,10 +43,11 @@ impl TableMigration for Peer { .table(Self::Table) .if_not_exists() .col(pk_auto(Self::Id)) + .col(string_len(Self::PeerId, 255)) .col(timestamp(Self::CreatedAt)) .col(timestamp(Self::UpdatedAt)) .col(timestamp(Self::ExpiresAt)) - .col(string_len_uniq(Self::PeerId, 255)) + .col(text_uniq(Self::Address)) .to_owned() ).await?; manager.create_index( @@ -53,53 +57,32 @@ impl TableMigration for Peer { .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() + manager.create_index( + Index::create() + .name(IDX_PEER_ADDRESS) .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) - ) + .col(Self::Address) .to_owned() ).await?; manager.create_index( Index::create() - .name(IDX_ADDRESS_MULTIADDRESS) + .name(IDX_PEER_CREATED_AT) .table(Self::Table) - .col(Self::MultiAddress) + .col(Self::CreatedAt) + .to_owned() + ).await?; + manager.create_index( + Index::create() + .name(IDX_PEER_UPDATED_AT) + .table(Self::Table) + .col(Self::UpdatedAt) + .to_owned() + ).await?; + manager.create_index( + Index::create() + .name(IDX_PEER_EXPIRES_AT) + .table(Self::Table) + .col(Self::ExpiresAt) .to_owned() ).await?; Ok(()) diff --git a/lazy-supplements-core/src/config/storage.rs b/lazy-supplements-core/src/config/storage.rs index b3cbebe..86ce924 100644 --- a/lazy-supplements-core/src/config/storage.rs +++ b/lazy-supplements-core/src/config/storage.rs @@ -2,6 +2,9 @@ use std::path::PathBuf; #[cfg(feature="desktop")] use clap::Args; + +#[cfg(any(test, feature="test"))] +use tempfile::tempdir; use crate::{config::{ConfigError, PartialConfig}}; use libp2p::mdns::Config; use serde::{Deserialize, Serialize}; @@ -30,8 +33,9 @@ impl StorageConfig { #[cfg(any(test, feature="test"))] impl TestDefault for StorageConfig { fn test_default() -> Self { - let temp_path = tempfile::NamedTempFile::new().unwrap().into_temp_path().keep().unwrap(); - Self { data_directory: temp_path.clone(), cache_directory: temp_path } + + let temp_dir = tempdir().unwrap().keep(); + Self { data_directory: temp_dir.clone(), cache_directory: temp_dir } } } diff --git a/lazy-supplements-core/src/data/mod.rs b/lazy-supplements-core/src/data/mod.rs index 0bfdf3e..25d0085 100644 --- a/lazy-supplements-core/src/data/mod.rs +++ b/lazy-supplements-core/src/data/mod.rs @@ -1,2 +1,3 @@ pub mod entity; -pub mod migration; \ No newline at end of file +pub mod migration; +pub mod value; \ No newline at end of file diff --git a/lazy-supplements-core/src/data/value/mod.rs b/lazy-supplements-core/src/data/value/mod.rs new file mode 100644 index 0000000..b32b175 --- /dev/null +++ b/lazy-supplements-core/src/data/value/mod.rs @@ -0,0 +1,5 @@ +mod multiaddr; +mod peer_id; + +pub use multiaddr::MultiaddrValue; +pub use peer_id::PeerIdValue; \ No newline at end of file diff --git a/lazy-supplements-core/src/data/value/multiaddr.rs b/lazy-supplements-core/src/data/value/multiaddr.rs new file mode 100644 index 0000000..f4de622 --- /dev/null +++ b/lazy-supplements-core/src/data/value/multiaddr.rs @@ -0,0 +1,68 @@ +use std::str::FromStr; + +use libp2p::Multiaddr; +use sea_orm::{sea_query::ValueTypeErr, DbErr}; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] +pub struct MultiaddrValue(Multiaddr); + +impl From for MultiaddrValue { + fn from(source: Multiaddr) -> Self { + Self(source) + } +} +impl From for Multiaddr { + fn from(source: MultiaddrValue) -> Self { + source.0 + } +} + +impl From for sea_orm::Value { + fn from(value: MultiaddrValue) -> Self { + Self::from(value.0.to_string()) + } +} + +impl sea_orm::TryGetable for MultiaddrValue { + fn try_get_by(res: &sea_orm::QueryResult, idx: I) + -> std::result::Result { + match ::try_get_by(res, idx){ + Ok(x) => match Multiaddr::from_str(&x) { + Ok(y) => Ok(Self(y)), + Err(_) => Err(DbErr::Type("Multiaddr".to_string()).into()), + }, + Err(x) => Err(x), + } + } +} + +impl sea_orm::sea_query::ValueType for MultiaddrValue { + fn try_from(v: sea_orm::Value) -> std::result::Result { + match ::try_from(v) { + Ok(x) => match Multiaddr::from_str(&x) { + Ok(y) => Ok(Self(y)), + Err(_) => Err(ValueTypeErr{}), + }, + Err(e) => Err(e) + } + } + + fn type_name() -> std::string::String { + stringify!(MultiaddrValue).to_owned() + } + + fn array_type() -> sea_orm::sea_query::ArrayType { + sea_orm::sea_query::ArrayType::String + } + + fn column_type() -> sea_orm::sea_query::ColumnType { + sea_orm::sea_query::ColumnType::Text + } +} + +impl sea_orm::sea_query::Nullable for MultiaddrValue { + fn null() -> sea_orm::Value { + ::null() + } +} \ No newline at end of file diff --git a/lazy-supplements-core/src/data/value/peer_id.rs b/lazy-supplements-core/src/data/value/peer_id.rs new file mode 100644 index 0000000..e28b5d4 --- /dev/null +++ b/lazy-supplements-core/src/data/value/peer_id.rs @@ -0,0 +1,68 @@ +use std::str::FromStr; + +use libp2p::PeerId; +use sea_orm::{sea_query::ValueTypeErr, DbErr}; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq)] +pub struct PeerIdValue(PeerId); + +impl From for PeerIdValue { + fn from(source: PeerId) -> Self { + Self(source) + } +} +impl From for PeerId { + fn from(source: PeerIdValue) -> Self { + source.0 + } +} + +impl From for sea_orm::Value { + fn from(value: PeerIdValue) -> Self { + Self::from(value.0.to_string()) + } +} + +impl sea_orm::TryGetable for PeerIdValue { + fn try_get_by(res: &sea_orm::QueryResult, idx: I) + -> std::result::Result { + match ::try_get_by(res, idx){ + Ok(x) => match PeerId::from_str(&x) { + Ok(y) => Ok(Self(y)), + Err(_) => Err(DbErr::Type("PeerId".to_string()).into()), + }, + Err(x) => Err(x), + } + } +} + +impl sea_orm::sea_query::ValueType for PeerIdValue { + fn try_from(v: sea_orm::Value) -> std::result::Result { + match ::try_from(v) { + Ok(x) => match PeerId::from_str(&x) { + Ok(y) => Ok(Self(y)), + Err(_) => Err(ValueTypeErr{}), + }, + Err(e) => Err(e) + } + } + + fn type_name() -> std::string::String { + stringify!(PeerIdValue).to_owned() + } + + fn array_type() -> sea_orm::sea_query::ArrayType { + sea_orm::sea_query::ArrayType::String + } + + fn column_type() -> sea_orm::sea_query::ColumnType { + sea_orm::sea_query::ColumnType::Text + } +} + +impl sea_orm::sea_query::Nullable for PeerIdValue { + fn null() -> sea_orm::Value { + ::null() + } +} \ No newline at end of file diff --git a/lazy-supplements-core/src/p2p/mod.rs b/lazy-supplements-core/src/p2p/mod.rs index 24bccac..e4931ae 100644 --- a/lazy-supplements-core/src/p2p/mod.rs +++ b/lazy-supplements-core/src/p2p/mod.rs @@ -40,10 +40,8 @@ impl Event { match PeerEntity::find().filter(PeerColumn::PeerId.contains(&peer.0.to_string())).one(CACHE_DATABASE_CONNECTION.get()).await { Ok(_) => {} Err(_) => { - ActivePeerModel{ - peer_id: Set(peer.0.to_string()), - ..ActivePeerModel::new() - }.insert(CACHE_DATABASE_CONNECTION.get()).await; + ActivePeerModel::new(peer.0.clone(), peer.1.clone()) + .insert(CACHE_DATABASE_CONNECTION.get()).await; } } } diff --git a/lazy-supplements-core/src/tests.rs b/lazy-supplements-core/src/tests.rs index e8dd1e5..50d4ffc 100644 --- a/lazy-supplements-core/src/tests.rs +++ b/lazy-supplements-core/src/tests.rs @@ -1,5 +1,7 @@ use std::{path::PathBuf, sync::LazyLock}; +use sea_orm::{sea_query::{FromValueTuple, IntoValueTuple, ValueType}, ActiveModelBehavior, ActiveModelTrait, ColumnTrait, Condition, DatabaseConnection, EntityTrait, IntoActiveModel, ModelTrait, PrimaryKeyToColumn, PrimaryKeyTrait, Value}; +use sea_orm::QueryFilter; use tempfile::TempDir; use crate::{ config::PartialConfig, message::Message}; @@ -43,4 +45,4 @@ where T: DeserializeOwned + Serialize + PartialEq + std::fmt::Debug let buf = toml::to_string(&src).unwrap(); let dst: T = toml::from_str(&buf).unwrap(); assert_eq!(src, dst); -} \ No newline at end of file +}