Fix global config
This commit is contained in:
parent
e24ff770a5
commit
2cb1f50f57
15 changed files with 106 additions and 95 deletions
|
@ -18,37 +18,37 @@ use clap::Args;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
p2p: P2pConfig,
|
pub p2p: P2pConfig,
|
||||||
storage: StorageConfig,
|
pub storage: StorageConfig,
|
||||||
rpc: RpcConfig,
|
pub rpc: RpcConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature="desktop", derive(Args))]
|
#[cfg_attr(feature="desktop", derive(Args))]
|
||||||
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
|
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
|
||||||
pub struct PartialConfig {
|
pub struct PartialConfig {
|
||||||
#[cfg_attr(feature="desktop", command(flatten))]
|
#[cfg_attr(feature="desktop", command(flatten))]
|
||||||
p2p: PartialP2pConfig,
|
pub p2p: PartialP2pConfig,
|
||||||
#[cfg_attr(feature="desktop", command(flatten))]
|
#[cfg_attr(feature="desktop", command(flatten))]
|
||||||
storage: PartialStorageConfig,
|
pub storage: PartialStorageConfig,
|
||||||
#[cfg_attr(feature="desktop", command(flatten))]
|
#[cfg_attr(feature="desktop", command(flatten))]
|
||||||
rpc: PartialRpcConfig,
|
pub rpc: PartialRpcConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialConfig {
|
impl PartialConfig {
|
||||||
fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
p2p : PartialP2pConfig::empty().with_new_secret(),
|
p2p : PartialP2pConfig::empty().with_new_secret(),
|
||||||
storage: PartialStorageConfig::empty(),
|
storage: PartialStorageConfig::empty(),
|
||||||
rpc: PartialRpcConfig::empty(),
|
rpc: PartialRpcConfig::empty(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn from_toml(s: &str) -> Result<Self, toml::de::Error> {
|
pub fn from_toml(s: &str) -> Result<Self, toml::de::Error> {
|
||||||
toml::from_str(s)
|
toml::from_str(s)
|
||||||
}
|
}
|
||||||
fn into_toml(&self) -> Result<String, toml::ser::Error> {
|
pub 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, ConfigError>
|
pub async fn read_or_create<T>(path: T) -> Result<Self, ConfigError>
|
||||||
where
|
where
|
||||||
T: AsRef<Path>
|
T: AsRef<Path>
|
||||||
{
|
{
|
||||||
|
@ -57,7 +57,7 @@ impl PartialConfig {
|
||||||
}
|
}
|
||||||
Self::read_from(&path).await
|
Self::read_from(&path).await
|
||||||
}
|
}
|
||||||
async fn read_from<T>(path:T) -> Result<Self, ConfigError>
|
pub async fn read_from<T>(path:T) -> Result<Self, ConfigError>
|
||||||
where
|
where
|
||||||
T: AsRef<Path>
|
T: AsRef<Path>
|
||||||
{
|
{
|
||||||
|
@ -67,7 +67,7 @@ impl PartialConfig {
|
||||||
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<(), ConfigError>
|
pub async fn write_to<T>(&self, path:T) -> Result<(), ConfigError>
|
||||||
where
|
where
|
||||||
T: AsRef<Path>
|
T: AsRef<Path>
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,15 +1,46 @@
|
||||||
use crate::{config::{P2pConfig, StorageConfig}, error::Error, global::GlobalConstant};
|
use tempfile::TempDir;
|
||||||
|
use tokio::sync::OnceCell;
|
||||||
|
|
||||||
pub static STORAGE_CONFIG: GlobalConstant<StorageConfig> = GlobalConstant::const_new(stringify!(STORAGE_CONFIG));
|
use crate::{config::{Config, PartialP2pConfig, PartialRpcConfig, PartialStorageConfig, StorageConfig}, error::Error, global::GlobalConstant};
|
||||||
pub static P2P_CONFIG: GlobalConstant<P2pConfig> = GlobalConstant::const_new(stringify!(P2P_CONFIG));
|
|
||||||
|
|
||||||
#[cfg(test)]
|
pub static CONFIG: GlobalConfig = GlobalConfig::const_new();
|
||||||
mod tests {
|
pub struct GlobalConfig {
|
||||||
use crate::global::{config::P2P_CONFIG, STORAGE_CONFIG};
|
inner: OnceCell<Config>
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
impl GlobalConfig {
|
||||||
fn test_global_constant_names() {
|
pub const fn const_new() -> Self {
|
||||||
assert_eq!(STORAGE_CONFIG.name, stringify!(STORAGE_CONFIG));
|
Self{
|
||||||
assert_eq!(P2P_CONFIG.name, stringify!(P2P_CONFIG));
|
inner: OnceCell::const_new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub async fn get_or_init(&'static self, source: Config) -> &'static Config {
|
||||||
|
self.inner.get_or_init(|| async {
|
||||||
|
source
|
||||||
|
}).await
|
||||||
|
}
|
||||||
|
pub fn get(&'static self) -> Option<&'static Config> {
|
||||||
|
self.inner.get()
|
||||||
|
}
|
||||||
|
pub fn get_and_unwrap(&'static self) -> &'static Config {
|
||||||
|
self.get().expect(&format!("Config is uninitialized!"))
|
||||||
|
}
|
||||||
|
#[cfg(any(test, feature=test))]
|
||||||
|
pub async fn get_or_init_test(&'static self) -> &'static Config {
|
||||||
|
let temp_dir = TempDir::new().unwrap().keep();
|
||||||
|
let mut data_dir = temp_dir.clone();
|
||||||
|
data_dir.push("data");
|
||||||
|
let mut cache_dir = temp_dir;
|
||||||
|
cache_dir.push("cache");
|
||||||
|
|
||||||
|
|
||||||
|
self.get_or_init(Config {
|
||||||
|
p2p: PartialP2pConfig::default().with_new_secret().try_into().unwrap(),
|
||||||
|
storage: StorageConfig {
|
||||||
|
data_directory: data_dir,
|
||||||
|
cache_directory: cache_dir,
|
||||||
|
},
|
||||||
|
rpc: PartialRpcConfig::default().try_into().unwrap(),
|
||||||
|
}).await
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -44,12 +44,12 @@ pub use tests::*;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{cache::migration::CacheMigrator, data::migration::DataMigrator, global::STORAGE_CONFIG, tests::GlobalTestDefault};
|
use crate::{cache::migration::CacheMigrator, data::migration::DataMigrator, global::CONFIG, tests::GlobalTestDefault};
|
||||||
|
|
||||||
pub async fn get_or_init_test_data_database() -> &'static DatabaseConnection{
|
pub async fn get_or_init_test_data_database() -> &'static DatabaseConnection{
|
||||||
DATA_DATABASE_CONNECTION.get_or_init(STORAGE_CONFIG.get_or_init_test_default().await.get_data_database_path(), DataMigrator).await
|
DATA_DATABASE_CONNECTION.get_or_init(CONFIG.get_or_init_test_default().await.storage.get_cache_database_path(), DataMigrator).await
|
||||||
}
|
}
|
||||||
pub async fn get_or_init_test_cache_database() -> &'static DatabaseConnection{
|
pub async fn get_or_init_test_cache_database() -> &'static DatabaseConnection{
|
||||||
CACHE_DATABASE_CONNECTION.get_or_init(STORAGE_CONFIG.get_or_init_test_default().await.get_cache_database_path(), CacheMigrator).await
|
CACHE_DATABASE_CONNECTION.get_or_init(CONFIG.get_or_init_test_default()await.storage.get_cache_database_path(), CacheMigrator).await
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -58,7 +58,7 @@ impl<T> GlobalConstant<T> {
|
||||||
self.inner.get()
|
self.inner.get()
|
||||||
}
|
}
|
||||||
pub fn get_and_unwrap(&'static self) -> &'static T {
|
pub fn get_and_unwrap(&'static self) -> &'static T {
|
||||||
self.get().expect(&format!("{} is uninitialized!", &stringify!(self)))
|
self.get().expect(&format!("{} is uninitialized!", self.name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,20 +29,3 @@ pub trait TestDefault {
|
||||||
pub trait GlobalTestDefault<T: 'static> {
|
pub trait GlobalTestDefault<T: 'static> {
|
||||||
async fn get_or_init_test_default(&'static self) -> &'static T;
|
async fn get_or_init_test_default(&'static self) -> &'static T;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn test_cbor_serialize_deserialize<T>(src: T)
|
|
||||||
where T: DeserializeOwned + Serialize + PartialEq + std::fmt::Debug
|
|
||||||
{
|
|
||||||
let mut buf: Vec<u8> = Vec::new();
|
|
||||||
ciborium::into_writer(&src, &mut buf).unwrap();
|
|
||||||
let dst: T = ciborium::from_reader(buf.as_slice()).unwrap();
|
|
||||||
assert_eq!(src, dst);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn test_toml_serialize_deserialize<T>(src: T)
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
use std::{net::IpAddr, path::PathBuf};
|
use std::{net::IpAddr, path::PathBuf};
|
||||||
|
|
||||||
use clap::Args;
|
use clap::Args;
|
||||||
use caretta_core::config::{BaseConfig, ConfigError};
|
use caretta_core::config::{PartialConfig,PartialP2pConfig, PartialStorageConfig, ConfigError};
|
||||||
use crate::config::{PartialP2pConfig, PartialStorageConfig};
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
@ -13,9 +12,9 @@ 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<BaseConfig>,
|
pub file_content: Option<PartialConfig>,
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub args: BaseConfig,
|
pub args: PartialConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,9 +22,9 @@ impl ConfigArgs {
|
||||||
pub fn get_file_path_or_default(&self) -> PathBuf {
|
pub fn get_file_path_or_default(&self) -> PathBuf {
|
||||||
self.file_path.clone().unwrap_or((*DEFAULT_CONFIG_FILE_PATH).clone())
|
self.file_path.clone().unwrap_or((*DEFAULT_CONFIG_FILE_PATH).clone())
|
||||||
}
|
}
|
||||||
pub async fn get_or_read_file_content(&mut self) -> &mut BaseConfig {
|
pub async fn get_or_read_file_content(&mut self) -> &mut PartialConfig {
|
||||||
self.file_content.get_or_insert(
|
self.file_content.get_or_insert(
|
||||||
BaseConfig::read_from(self.get_file_path_or_default()).await.unwrap()
|
PartialConfig::read_from(self.get_file_path_or_default()).await.unwrap()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,11 @@ use std::path::PathBuf;
|
||||||
|
|
||||||
mod args;
|
mod args;
|
||||||
mod device;
|
mod device;
|
||||||
mod server;
|
mod peer;
|
||||||
|
|
||||||
pub use args::*;
|
pub use args::*;
|
||||||
pub use device::*;
|
pub use device::*;
|
||||||
pub use server::*;
|
pub use peer::*;
|
||||||
|
|
||||||
pub trait RunnableCommand {
|
pub trait RunnableCommand {
|
||||||
async fn run(self);
|
async fn run(self);
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
use clap::Args;
|
|
||||||
use caretta_core::utils::runnable::Runnable;
|
|
||||||
use libp2p::{noise, ping, swarm::{NetworkBehaviour, SwarmEvent}, tcp, yamux, Swarm};
|
|
||||||
|
|
||||||
use crate::{error::Error, global::P2P_CONFIG};
|
|
||||||
|
|
||||||
use super::ConfigArgs;
|
|
||||||
|
|
||||||
#[derive(Args, Debug)]
|
|
||||||
pub struct ServerCommandArgs {
|
|
||||||
#[command(flatten)]
|
|
||||||
config: ConfigArgs,
|
|
||||||
}
|
|
||||||
impl Runnable for ServerCommandArgs {
|
|
||||||
async fn run(self) {
|
|
||||||
P2P_CONFIG.get_and_unwrap().clone().launch_swarm();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,5 @@
|
||||||
[package]
|
[package]
|
||||||
name = "caretta-examples-core"
|
name = "caretta-example-core"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
description.workspace = true
|
description.workspace = true
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[package]
|
[package]
|
||||||
name = "caretta-examples-desktop"
|
name = "caretta-example-desktop"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
@ -7,12 +7,8 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap.workspace = true
|
clap.workspace = true
|
||||||
dioxus.workspace = true
|
caretta = { path = "../..", features = ["desktop"] }
|
||||||
caretta-desktop.path = "../../desktop"
|
caretta-example-core.path = "../core"
|
||||||
caretta-examples-core.path = "../core"
|
libp2p.workspace = true
|
||||||
|
tokio.workspace = true
|
||||||
|
|
||||||
[features]
|
|
||||||
default = ["desktop"]
|
|
||||||
web = ["dioxus/web"]
|
|
||||||
desktop = ["dioxus/desktop"]
|
|
||||||
mobile = ["dioxus/mobile"]
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
mod server;
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use caretta_desktop::cli::*;
|
use caretta::cli::*;
|
||||||
|
pub use server::*;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct Cli {
|
pub struct Cli {
|
19
examples/desktop/src/cli/server.rs
Normal file
19
examples/desktop/src/cli/server.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
use clap::Args;
|
||||||
|
use caretta::{error::Error, utils::runnable::Runnable};
|
||||||
|
use libp2p::{noise, ping, swarm::{NetworkBehaviour, SwarmEvent}, tcp, yamux, Swarm};
|
||||||
|
|
||||||
|
use super::ConfigArgs;
|
||||||
|
|
||||||
|
#[derive(Args, Debug)]
|
||||||
|
pub struct ServerCommandArgs {
|
||||||
|
#[command(flatten)]
|
||||||
|
config: ConfigArgs,
|
||||||
|
}
|
||||||
|
impl Runnable for ServerCommandArgs {
|
||||||
|
async fn run(self) {
|
||||||
|
let swarm_handler = P2P_CONFIG.get_and_unwrap().clone().launch_swarm();
|
||||||
|
let server_handler = caretta_example_core::rpc::server::start_server();
|
||||||
|
|
||||||
|
let (swarm_result, server_result) = tokio::try_join!(swarm_handler, server_handler).unwrap();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,11 @@
|
||||||
|
use crate::cli::Cli;
|
||||||
|
|
||||||
mod cli;
|
mod cli;
|
||||||
mod ipc;
|
mod ipc;
|
||||||
fn main() {
|
|
||||||
dioxus::launch(caretta_examples_core::ui::plain::App);
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
let args = Cli::parse();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,9 @@
|
||||||
[package]
|
[package]
|
||||||
name = "caretta-examples-mobile"
|
name = "caretta-example-mobile"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["fluo10 <fluo10.dev@fireturtle.net>"]
|
authors = ["fluo10 <fluo10.dev@fireturtle.net>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
dioxus.workspace = true
|
dioxus.workspace = true
|
||||||
caretta-examples-core.path = "../core"
|
caretta-example-core.path = "../core"
|
||||||
|
|
||||||
[features]
|
|
||||||
default = ["mobile"]
|
|
||||||
web = ["dioxus/web"]
|
|
||||||
desktop = ["dioxus/desktop"]
|
|
||||||
mobile = ["dioxus/mobile"]
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
pub use caretta_core::*;
|
pub use caretta_core::*;
|
||||||
#[cfg(desktop)]
|
#[cfg(feature = "desktop")]
|
||||||
pub use caretta_desktop::*;
|
pub use caretta_desktop::*;
|
||||||
#[cfg(mobile)]
|
#[cfg(feature = "mobile")]
|
||||||
pub use caretta_mobile::*;
|
pub use caretta_mobile::*;
|
Loading…
Add table
Reference in a new issue