Fix errors
This commit is contained in:
parent
1adebe17e4
commit
9c960a9d59
16 changed files with 138 additions and 238 deletions
|
@ -10,11 +10,11 @@ use serde::{Deserialize, Serialize};
|
||||||
use crate::data::value::{MultiaddrValue, PeerIdValue};
|
use crate::data::value::{MultiaddrValue, PeerIdValue};
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize)]
|
||||||
#[sea_orm(table_name = "peer")]
|
#[sea_orm(table_name = "peer")]
|
||||||
pub struct Model {
|
pub struct Model {
|
||||||
#[sea_orm(primary_key)]
|
#[sea_orm(primary_key)]
|
||||||
pub id: u32,
|
pub id: Uuid,
|
||||||
#[sea_orm(indexed)]
|
#[sea_orm(indexed)]
|
||||||
pub created_at: DateTimeUtc,
|
pub created_at: DateTimeUtc,
|
||||||
#[sea_orm(indexed)]
|
#[sea_orm(indexed)]
|
||||||
|
|
|
@ -42,7 +42,7 @@ impl TableMigration for Peer {
|
||||||
Table::create()
|
Table::create()
|
||||||
.table(Self::Table)
|
.table(Self::Table)
|
||||||
.if_not_exists()
|
.if_not_exists()
|
||||||
.col(pk_auto(Self::Id))
|
.col(pk_uuid(Self::Id))
|
||||||
.col(string_len(Self::PeerId, 255))
|
.col(string_len(Self::PeerId, 255))
|
||||||
.col(timestamp(Self::CreatedAt))
|
.col(timestamp(Self::CreatedAt))
|
||||||
.col(timestamp(Self::UpdatedAt))
|
.col(timestamp(Self::UpdatedAt))
|
||||||
|
|
|
@ -2,4 +2,10 @@
|
||||||
pub enum ConfigError {
|
pub enum ConfigError {
|
||||||
#[error("missing config: {0}")]
|
#[error("missing config: {0}")]
|
||||||
MissingConfig(String),
|
MissingConfig(String),
|
||||||
|
#[error("Io error: {0}")]
|
||||||
|
Io(#[from] std::io::Error),
|
||||||
|
#[error("Toml Deserialization Error")]
|
||||||
|
TomlDerialization(#[from] toml::de::Error),
|
||||||
|
#[error("Toml Serialization Error")]
|
||||||
|
TomlSerialization(#[from] toml::ser::Error),
|
||||||
}
|
}
|
|
@ -3,7 +3,7 @@ mod storage;
|
||||||
mod p2p;
|
mod p2p;
|
||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use crate::{error::Error, utils::{emptiable::Emptiable, mergeable::Mergeable}};
|
use crate::{utils::{emptiable::Emptiable, mergeable::Mergeable}};
|
||||||
pub use error::ConfigError;
|
pub use error::ConfigError;
|
||||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ pub trait PartialConfig: Emptiable + From<Self::Config> + Mergeable {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait PartialCoreConfig: DeserializeOwned + Serialize {
|
pub trait BaseConfig: DeserializeOwned + Serialize {
|
||||||
fn new() -> Self;
|
fn new() -> Self;
|
||||||
fn from_toml(s: &str) -> Result<Self, toml::de::Error> {
|
fn from_toml(s: &str) -> Result<Self, toml::de::Error> {
|
||||||
toml::from_str(s)
|
toml::from_str(s)
|
||||||
|
@ -27,7 +27,7 @@ pub trait PartialCoreConfig: DeserializeOwned + Serialize {
|
||||||
fn into_toml(&self) -> Result<String, toml::ser::Error> {
|
fn into_toml(&self) -> Result<String, toml::ser::Error> {
|
||||||
toml::to_string(self)
|
toml::to_string(self)
|
||||||
}
|
}
|
||||||
async fn read_or_create<T>(path: T) -> Result<Self, Error>
|
async fn read_or_create<T>(path: T) -> Result<Self, ConfigError>
|
||||||
where
|
where
|
||||||
T: AsRef<Path>
|
T: AsRef<Path>
|
||||||
{
|
{
|
||||||
|
@ -36,7 +36,7 @@ pub trait PartialCoreConfig: DeserializeOwned + Serialize {
|
||||||
}
|
}
|
||||||
Self::read_from(&path).await
|
Self::read_from(&path).await
|
||||||
}
|
}
|
||||||
async fn read_from<T>(path:T) -> Result<Self, Error>
|
async fn read_from<T>(path:T) -> Result<Self, ConfigError>
|
||||||
where
|
where
|
||||||
T: AsRef<Path>
|
T: AsRef<Path>
|
||||||
{
|
{
|
||||||
|
@ -46,7 +46,7 @@ pub trait PartialCoreConfig: DeserializeOwned + Serialize {
|
||||||
let config: Self = toml::from_str(&content)?;
|
let config: Self = toml::from_str(&content)?;
|
||||||
Ok(config)
|
Ok(config)
|
||||||
}
|
}
|
||||||
async fn write_to<T>(&self, path:T) -> Result<(), Error>
|
async fn write_to<T>(&self, path:T) -> Result<(), ConfigError>
|
||||||
where
|
where
|
||||||
T: AsRef<Path>
|
T: AsRef<Path>
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,7 +3,8 @@ use std::{net::{IpAddr, Ipv4Addr}, ops, path::{Path, PathBuf}};
|
||||||
use base64::{prelude::BASE64_STANDARD, Engine};
|
use base64::{prelude::BASE64_STANDARD, Engine};
|
||||||
#[cfg(feature="desktop")]
|
#[cfg(feature="desktop")]
|
||||||
use clap::Args;
|
use clap::Args;
|
||||||
use libp2p::{identity::{self, DecodingError, Keypair}, noise, ping, tcp, yamux, Swarm};
|
use futures::StreamExt;
|
||||||
|
use libp2p::{identity::{self, DecodingError, Keypair}, noise, ping, swarm::SwarmEvent, tcp, yamux, Swarm};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tokio::{fs::File, io::{AsyncReadExt, AsyncWriteExt}};
|
use tokio::{fs::File, io::{AsyncReadExt, AsyncWriteExt}};
|
||||||
use tracing_subscriber::EnvFilter;
|
use tracing_subscriber::EnvFilter;
|
||||||
|
@ -11,7 +12,7 @@ use tracing_subscriber::EnvFilter;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::PartialConfig,
|
config::PartialConfig,
|
||||||
error::Error, p2p, utils::emptiable::Emptiable
|
error::Error, p2p, utils::{emptiable::Emptiable, mergeable::Mergeable}
|
||||||
};
|
};
|
||||||
|
|
||||||
static DEFAULT_P2P_LISTEN_IPS: &[IpAddr] = &[IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))];
|
static DEFAULT_P2P_LISTEN_IPS: &[IpAddr] = &[IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))];
|
||||||
|
@ -30,7 +31,7 @@ fn base64_to_keypair(base64: &str) -> Result<Keypair, Error> {
|
||||||
Ok(Keypair::from_protobuf_encoding(&vec)?)
|
Ok(Keypair::from_protobuf_encoding(&vec)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Deserialize, Serialize,)]
|
||||||
pub struct P2pConfig {
|
pub struct P2pConfig {
|
||||||
#[serde(with = "keypair_parser")]
|
#[serde(with = "keypair_parser")]
|
||||||
pub secret: Keypair,
|
pub secret: Keypair,
|
||||||
|
@ -39,7 +40,7 @@ pub struct P2pConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl P2pConfig {
|
impl P2pConfig {
|
||||||
pub async fn try_into_swarm (self) -> Result<Swarm<p2p::Behaviour>, Error> {
|
async fn try_into_swarm (self) -> Result<Swarm<p2p::Behaviour>, Error> {
|
||||||
let mut swarm = libp2p::SwarmBuilder::with_existing_identity(self.secret)
|
let mut swarm = libp2p::SwarmBuilder::with_existing_identity(self.secret)
|
||||||
.with_tokio()
|
.with_tokio()
|
||||||
.with_tcp(
|
.with_tcp(
|
||||||
|
@ -52,6 +53,22 @@ impl P2pConfig {
|
||||||
swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse()?)?;
|
swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse()?)?;
|
||||||
Ok(swarm)
|
Ok(swarm)
|
||||||
}
|
}
|
||||||
|
pub async fn launch_swarm(self) -> Result<(), Error>{
|
||||||
|
let mut swarm = self.try_into_swarm().await?;
|
||||||
|
loop{
|
||||||
|
let swarm_event = swarm.select_next_some().await;
|
||||||
|
tokio::spawn(async move{
|
||||||
|
match swarm_event {
|
||||||
|
SwarmEvent::NewListenAddr { address, .. } => println!("Listening on {address:?}"),
|
||||||
|
SwarmEvent::Behaviour(event) => {
|
||||||
|
println!("{event:?}");
|
||||||
|
event.run().await;
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<PartialP2pConfig> for P2pConfig {
|
impl TryFrom<PartialP2pConfig> for P2pConfig {
|
||||||
|
@ -86,7 +103,6 @@ mod keypair_parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature="desktop",derive(Args))]
|
#[cfg_attr(feature="desktop",derive(Args))]
|
||||||
#[cfg_attr(feature="macros", derive(Emptiable))]
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
|
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
|
||||||
pub struct PartialP2pConfig {
|
pub struct PartialP2pConfig {
|
||||||
#[cfg_attr(feature="desktop",arg(long))]
|
#[cfg_attr(feature="desktop",arg(long))]
|
||||||
|
@ -123,7 +139,33 @@ impl Default for PartialP2pConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Emptiable for PartialP2pConfig {
|
||||||
|
fn empty() -> Self {
|
||||||
|
Self{
|
||||||
|
secret: None,
|
||||||
|
listen_ips: None,
|
||||||
|
port: None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_empty(&self) -> bool {
|
||||||
|
self.secret.is_none() && self.listen_ips.is_none() && self.port.is_none()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mergeable for PartialP2pConfig {
|
||||||
|
fn merge(&mut self, mut other: Self) {
|
||||||
|
if let Some(x) = other.secret.take() {
|
||||||
|
let _ = self.secret.insert(x);
|
||||||
|
};
|
||||||
|
if let Some(x) = other.listen_ips.take() {
|
||||||
|
let _ = self.listen_ips.insert(x);
|
||||||
|
};
|
||||||
|
if let Some(x) = other.port.take() {
|
||||||
|
let _ = self.port.insert(x);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -5,7 +5,7 @@ use clap::Args;
|
||||||
|
|
||||||
#[cfg(any(test, feature="test"))]
|
#[cfg(any(test, feature="test"))]
|
||||||
use tempfile::tempdir;
|
use tempfile::tempdir;
|
||||||
use crate::{config::{ConfigError, PartialConfig}, utils::emptiable::Emptiable};
|
use crate::{config::{ConfigError, PartialConfig}, utils::{emptiable::Emptiable, mergeable::Mergeable}};
|
||||||
use libp2p::mdns::Config;
|
use libp2p::mdns::Config;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
@ -50,7 +50,6 @@ impl TryFrom<PartialStorageConfig> for StorageConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg_attr(feature="desktop", derive(Args))]
|
#[cfg_attr(feature="desktop", derive(Args))]
|
||||||
#[cfg_attr(feature="macros", derive(Emptiable))]
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
pub struct PartialStorageConfig {
|
pub struct PartialStorageConfig {
|
||||||
#[cfg_attr(feature="desktop", arg(long))]
|
#[cfg_attr(feature="desktop", arg(long))]
|
||||||
|
@ -66,4 +65,27 @@ impl From<StorageConfig> for PartialStorageConfig {
|
||||||
cache_directory: Some(config.cache_directory),
|
cache_directory: Some(config.cache_directory),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Emptiable for PartialStorageConfig {
|
||||||
|
fn empty() -> Self {
|
||||||
|
Self {
|
||||||
|
data_directory: None,
|
||||||
|
cache_directory: None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_empty(&self) -> bool {
|
||||||
|
self.data_directory.is_none() && self.cache_directory.is_none()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Mergeable for PartialStorageConfig {
|
||||||
|
fn merge(&mut self, mut other: Self) {
|
||||||
|
if let Some(x) = other.data_directory.take() {
|
||||||
|
let _ = self.data_directory.insert(x);
|
||||||
|
};
|
||||||
|
if let Some(x) = other.cache_directory.take() {
|
||||||
|
let _ = self.cache_directory.insert(x);
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -10,9 +10,9 @@ use sea_orm_migration::MigratorTrait;
|
||||||
use tokio::sync::{OnceCell, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
use tokio::sync::{OnceCell, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||||
|
|
||||||
mod peers;
|
mod peers;
|
||||||
pub use peers::PEERS;
|
pub use peers::*;
|
||||||
mod config;
|
mod config;
|
||||||
pub use config::STORAGE_CONFIG;
|
pub use config::*;
|
||||||
mod database_connection;
|
mod database_connection;
|
||||||
pub use database_connection::*;
|
pub use database_connection::*;
|
||||||
use uuid::{ContextV7, Timestamp, Uuid};
|
use uuid::{ContextV7, Timestamp, Uuid};
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#[cfg(feature="macros")]
|
||||||
|
pub use lazy_supplements_macros::Mergeable;
|
||||||
pub trait Mergeable: Sized {
|
pub trait Mergeable: Sized {
|
||||||
fn merge(&mut self, other: Self);
|
fn merge(&mut self, other: Self);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::{net::IpAddr, path::PathBuf};
|
use std::{net::IpAddr, path::PathBuf};
|
||||||
|
|
||||||
use clap::Args;
|
use clap::Args;
|
||||||
use lazy_supplements_core::config::ConfigError;
|
use lazy_supplements_core::config::{BaseConfig, ConfigError};
|
||||||
use crate::config::{PartialP2pConfig, PartialStorageConfig};
|
use crate::config::{PartialP2pConfig, PartialStorageConfig};
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use crate::config::PartialUnixConfig;
|
use crate::config::PartialUnixConfig;
|
||||||
|
@ -9,46 +9,29 @@ use crate::config::PartialUnixConfig;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::PartialDesktopConfig,
|
config::DesktopBaseConfig,
|
||||||
error::Error,
|
error::Error,
|
||||||
global::{DEFAULT_CONFIG_FILE_PATH, DEFAULT_PARTIAL_CORE_CONFIG,}
|
global::DEFAULT_CONFIG_FILE_PATH
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Args, Clone, Debug)]
|
#[derive(Args, Clone, Debug)]
|
||||||
pub struct ConfigArgs {
|
pub struct ConfigArgs {
|
||||||
#[arg(short = "c", long = "config")]
|
#[arg(short = 'c', long = "config")]
|
||||||
pub file_path: Option<PathBuf>,
|
pub file_path: Option<PathBuf>,
|
||||||
#[arg(skip)]
|
#[arg(skip)]
|
||||||
pub file_content: Option<Result<PartialDesktopConfig, ConfigError>>,
|
pub file_content: Option<DesktopBaseConfig>,
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub args: PartialDesktopConfig,
|
pub args: DesktopBaseConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl ConfigArgs {
|
impl ConfigArgs {
|
||||||
pub fn get_file_path_or_default(&self) -> PathBuf {
|
pub fn get_file_path_or_default(&self) -> PathBuf {
|
||||||
self.file_path.unwrap_or(DEFAULT_CONFIG_FILE_PATH)
|
self.file_path.clone().unwrap_or((*DEFAULT_CONFIG_FILE_PATH).clone())
|
||||||
}
|
}
|
||||||
pub async fn get_or_read_file_content(&mut self) -> Result<PartialDesktopConfig, ConfigError> {
|
pub async fn get_or_read_file_content(&mut self) -> &mut DesktopBaseConfig {
|
||||||
self.file_content.get_or_insert(
|
self.file_content.get_or_insert(
|
||||||
PartialDesktopConfig::read_from(self.get_config_path_or_default()).await
|
DesktopBaseConfig::read_from(self.get_file_path_or_default()).await.unwrap()
|
||||||
).clone()
|
)
|
||||||
}
|
|
||||||
pub fn get_config_path_or_default(&self) -> PathBuf {
|
|
||||||
if let Some(x) = self.config.as_ref() {
|
|
||||||
x.clone()
|
|
||||||
} else {
|
|
||||||
DEFAULT_CONFIG_FILE_PATH.to_path_buf()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub async fn try_into_partial_core_config(self) -> Result<PartialCoreConfig, Error> {
|
|
||||||
let mut config = PartialCoreConfig::read_from(self.get_config_path_or_default()).await?;
|
|
||||||
config.merge(self.core_config.into());
|
|
||||||
Ok(config)
|
|
||||||
}
|
|
||||||
pub async fn try_into_core_config(self) -> Result<CoreConfig, Error> {
|
|
||||||
let mut config = DEFAULT_PARTIAL_CORE_CONFIG.clone();
|
|
||||||
config.merge(self.try_into_partial_core_config().await?);
|
|
||||||
config.try_into()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,14 +12,8 @@ pub use ping::DevicePingCommandArgs;
|
||||||
pub use remove::DeviceRemoveCommandArgs;
|
pub use remove::DeviceRemoveCommandArgs;
|
||||||
pub use scan::DeviceScanCommandArgs;
|
pub use scan::DeviceScanCommandArgs;
|
||||||
|
|
||||||
use std::{net::IpAddr, ops::Mul, path::PathBuf, str::FromStr};
|
|
||||||
|
|
||||||
use clap::{Args, Parser, Subcommand};
|
use clap::{Args, Parser, Subcommand};
|
||||||
|
|
||||||
use crate::{cli::ServerArgs, error::Error};
|
|
||||||
|
|
||||||
use super::ConfigArgs;
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Args, Runnable)]
|
#[derive(Debug, Args, Runnable)]
|
||||||
pub struct DeviceCommandArgs {
|
pub struct DeviceCommandArgs {
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
use clap::Args;
|
use clap::Args;
|
||||||
|
use lazy_supplements_core::utils::runnable::Runnable;
|
||||||
use libp2p::{noise, ping, swarm::{NetworkBehaviour, SwarmEvent}, tcp, yamux, Swarm};
|
use libp2p::{noise, ping, swarm::{NetworkBehaviour, SwarmEvent}, tcp, yamux, Swarm};
|
||||||
|
|
||||||
use crate::{error::Error, global::GLOBAL};
|
use crate::{error::Error, global::P2P_CONFIG};
|
||||||
|
|
||||||
use super::ConfigArgs;
|
use super::ConfigArgs;
|
||||||
|
|
||||||
#[derive(Args, Debug)]
|
#[derive(Args, Debug)]
|
||||||
pub struct ServerArgs {
|
pub struct ServerCommandArgs {
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
config: ConfigArgs,
|
config: ConfigArgs,
|
||||||
}
|
}
|
||||||
impl ServerArgs {
|
impl Runnable for ServerCommandArgs {
|
||||||
pub async fn start_server(self) -> Result<(), Error>{
|
async fn run(self) {
|
||||||
let _ = crate::global::GLOBAL.get_or_init_core_config(self.config.try_into_core_config().await?).await;
|
P2P_CONFIG.get_and_unwrap().clone().launch_swarm();
|
||||||
GLOBAL.launch_swarm().await
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,8 +4,10 @@ pub mod unix;
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
pub mod windows;
|
pub mod windows;
|
||||||
|
|
||||||
|
use clap::Args;
|
||||||
pub use lazy_supplements_core::config::*;
|
pub use lazy_supplements_core::config::*;
|
||||||
|
|
||||||
|
use lazy_supplements_core::utils::{emptiable::Emptiable, mergeable::Mergeable};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
pub use unix::*;
|
pub use unix::*;
|
||||||
|
@ -13,15 +15,18 @@ pub use unix::*;
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
pub use windows::*;
|
pub use windows::*;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Args, Clone, Debug, Deserialize, Emptiable, Mergeable, Serialize)]
|
||||||
pub struct PartialDesktopConfig {
|
pub struct DesktopBaseConfig {
|
||||||
|
#[command(flatten)]
|
||||||
p2p: PartialP2pConfig,
|
p2p: PartialP2pConfig,
|
||||||
|
#[command(flatten)]
|
||||||
storage: PartialStorageConfig,
|
storage: PartialStorageConfig,
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
|
#[command(flatten)]
|
||||||
unix: PartialUnixConfig,
|
unix: PartialUnixConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialConfigRoot for PartialDesktopConfig {
|
impl BaseConfig for DesktopBaseConfig {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
p2p : PartialP2pConfig::empty().with_new_secret(),
|
p2p : PartialP2pConfig::empty().with_new_secret(),
|
||||||
|
@ -29,4 +34,20 @@ impl PartialConfigRoot for PartialDesktopConfig {
|
||||||
unix: PartialUnixConfig::empty(),
|
unix: PartialUnixConfig::empty(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<PartialP2pConfig> for &DesktopBaseConfig {
|
||||||
|
fn into(self) -> PartialP2pConfig {
|
||||||
|
self.p2p.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Into<PartialStorageConfig> for &DesktopBaseConfig {
|
||||||
|
fn into(self) -> PartialStorageConfig {
|
||||||
|
self.storage.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Into<PartialUnixConfig> for &DesktopBaseConfig {
|
||||||
|
fn into(self) -> PartialUnixConfig {
|
||||||
|
self.unix.clone()
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use clap::Args;
|
use clap::Args;
|
||||||
use lazy_supplements_core::config::PartialConfig;
|
use lazy_supplements_core::{config::PartialConfig, utils::{emptiable::Emptiable, mergeable::Mergeable}};
|
||||||
use libp2p::mdns::Config;
|
use libp2p::mdns::Config;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
@ -20,11 +20,17 @@ impl TryFrom<PartialUnixConfig> for UnixConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args, Clone, Debug, Deserialize, Serialize)]
|
#[derive(Args, Clone, Debug, Deserialize, Emptiable, Mergeable, Serialize)]
|
||||||
pub struct PartialUnixConfig {
|
pub struct PartialUnixConfig {
|
||||||
pub socket_path: Option<PathBuf>,
|
pub socket_path: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for PartialUnixConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<UnixConfig> for PartialUnixConfig {
|
impl From<UnixConfig> for PartialUnixConfig {
|
||||||
fn from(source: UnixConfig) -> Self {
|
fn from(source: UnixConfig) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -33,19 +39,4 @@ impl From<UnixConfig> for PartialUnixConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialConfig for PartialUnixConfig {
|
|
||||||
fn empty() -> Self {
|
|
||||||
Self { socket_path: None }
|
|
||||||
}
|
|
||||||
fn default() -> Self {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
fn is_empty(&self) -> bool {
|
|
||||||
self.socket_path.is_none()
|
|
||||||
}
|
|
||||||
fn merge(&mut self, other: Self) {
|
|
||||||
if let Some(x) = other.socket_path {
|
|
||||||
self.socket_path = Some(x);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use std::{path::PathBuf, sync::LazyLock};
|
use std::{path::PathBuf, sync::LazyLock};
|
||||||
|
|
||||||
use lazy_supplements_core::config::PartialCoreConfig;
|
|
||||||
pub use lazy_supplements_core::global::*;
|
pub use lazy_supplements_core::global::*;
|
||||||
|
|
||||||
pub static DEFAULT_DATA_DIR_PATH: LazyLock<PathBuf> = LazyLock::new(|| {
|
pub static DEFAULT_DATA_DIR_PATH: LazyLock<PathBuf> = LazyLock::new(|| {
|
||||||
|
@ -28,123 +27,3 @@ pub static DEFAULT_CONFIG_FILE_PATH: LazyLock<PathBuf> = LazyLock::new(|| {
|
||||||
pub static DEFAULT_DATABASE_FILE_PATH: LazyLock<PathBuf> = LazyLock::new(|| {
|
pub static DEFAULT_DATABASE_FILE_PATH: LazyLock<PathBuf> = LazyLock::new(|| {
|
||||||
DEFAULT_DATA_DIR_PATH.join(&*DEFAULT_DATABASE_FILE_NAME)
|
DEFAULT_DATA_DIR_PATH.join(&*DEFAULT_DATABASE_FILE_NAME)
|
||||||
});
|
});
|
||||||
|
|
||||||
pub static DEFAULT_PARTIAL_CORE_CONFIG: LazyLock<PartialCoreConfig> = LazyLock::new(|| {
|
|
||||||
PartialCoreConfig {
|
|
||||||
secret: None,
|
|
||||||
listen_ips: Some(DEFAULT_LISTEN_IPS.to_vec()),
|
|
||||||
port: Some(0),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
pub struct Global {
|
|
||||||
pub p2p_config: OnceCell<P2pConfig>,
|
|
||||||
pub main_database: OnceCell<DatabaseConnection>,
|
|
||||||
pub cache_database: OnceCell<DatabaseConnection>,
|
|
||||||
pub peers: OnceCell<RwLock<HashMap<PeerId, Multiaddr>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Global {
|
|
||||||
pub fn get_p2p_config(&self) -> Option<&P2pConfig> {
|
|
||||||
self.p2p_config.get()
|
|
||||||
}
|
|
||||||
pub async fn get_or_init_p2p_config(&self, config: P2pConfig) -> &P2pConfig {
|
|
||||||
self.p2p_config.get_or_init(|| async {config}).await
|
|
||||||
}
|
|
||||||
pub async fn get_or_init_peers(&self) -> &RwLock<HashMap<PeerId, Multiaddr>> {
|
|
||||||
self.peers.get_or_init(|| async {
|
|
||||||
RwLock::new(HashMap::new())
|
|
||||||
}).await
|
|
||||||
}
|
|
||||||
pub async fn read_peers(&self) -> tokio::sync::RwLockReadGuard<'_, HashMap<PeerId, Multiaddr>>{
|
|
||||||
self.get_or_init_peers().await.read().await
|
|
||||||
}
|
|
||||||
pub async fn write_peers(&self) -> tokio::sync::RwLockWriteGuard<'_, HashMap<PeerId, Multiaddr>>{
|
|
||||||
self.get_or_init_peers().await.write().await
|
|
||||||
}
|
|
||||||
pub async fn launch_swarm(&self) -> Result<(), Error> {
|
|
||||||
let mut swarm = self.get_p2p_config().unwrap().clone().try_into_swarm().await?;
|
|
||||||
loop{
|
|
||||||
let swarm_event = swarm.select_next_some().await;
|
|
||||||
tokio::spawn(async move{
|
|
||||||
match swarm_event {
|
|
||||||
SwarmEvent::NewListenAddr { address, .. } => println!("Listening on {address:?}"),
|
|
||||||
SwarmEvent::Behaviour(event) => {
|
|
||||||
println!("{event:?}");
|
|
||||||
event.run().await;
|
|
||||||
},
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GlobalDatabase for Global {
|
|
||||||
fn get_main_database(&self) -> Option<&DatabaseConnection> {
|
|
||||||
self.main_database.get()
|
|
||||||
}
|
|
||||||
async fn get_or_try_init_main_database<T, U>(&self, path: T, _: U) -> Result<&DatabaseConnection, Error>
|
|
||||||
where
|
|
||||||
T: AsRef<Path>,
|
|
||||||
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::<DatabaseConnection, DbErr>(db)
|
|
||||||
}).await?)
|
|
||||||
}
|
|
||||||
fn get_cache_database(&self) -> Option<&DatabaseConnection> {
|
|
||||||
self.cache_database.get()
|
|
||||||
}
|
|
||||||
async fn get_or_try_init_cache_database<T, U>(&self, path: T, _: U) -> Result<&DatabaseConnection, Error>
|
|
||||||
where
|
|
||||||
T: AsRef<Path>,
|
|
||||||
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::<DatabaseConnection, DbErr>(db)
|
|
||||||
}).await?)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[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, cache::migration::CacheMigrator, data::migration::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());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,16 +2,3 @@ mod response;
|
||||||
mod request;
|
mod request;
|
||||||
pub use response::*;
|
pub use response::*;
|
||||||
pub use request::*;
|
pub use request::*;
|
||||||
|
|
||||||
pub trait IpcRequest {
|
|
||||||
type IpcResponse: IpcResponse<IpcRequest = Self>;
|
|
||||||
async fn try_into_p2p_response(&self) -> Result<IpcResponse, Error> {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait IpcResponse {
|
|
||||||
type IpcRequest: IpcRequest<IpcResponse = Self>;
|
|
||||||
async fn try_from_ipc_request(&self) -> Result<IpcRequest, Error>;
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
use clap::{Parser, Subcommand};
|
|
||||||
use lazy_supplements_desktop::{cli::{ConfigArgs, NodeArgs, NodeCommand, ServerArgs}, global::{Global, GLOBAL}, *};
|
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
|
||||||
struct Cli {
|
|
||||||
#[command(subcommand)]
|
|
||||||
command: Command,
|
|
||||||
#[command(flatten)]
|
|
||||||
pub config: ConfigArgs,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Subcommand)]
|
|
||||||
enum Command {
|
|
||||||
Node(NodeArgs),
|
|
||||||
Server(ServerArgs),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[tokio::main]
|
|
||||||
async fn main() {
|
|
||||||
let cli = Cli::parse();
|
|
||||||
let _ = GLOBAL.get_or_init_core_config(cli.config.try_into_core_config().await.unwrap()).await;
|
|
||||||
match cli.command {
|
|
||||||
Command::Node(x) => x.run().await.unwrap(),
|
|
||||||
Command::Server(x) => x.start_server().await.unwrap(),
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue