From 89cc75f674c8b0131aa73cb7ce98765434b9ff9c Mon Sep 17 00:00:00 2001 From: Mg Pig Date: Tue, 4 Nov 2025 13:48:10 +0800 Subject: [PATCH] refactor: replace ConfigSource with bool parameter (#1516) --- easytier-contrib/easytier-ffi/src/lib.rs | 3 +- easytier-contrib/easytier-ohrs/src/lib.rs | 5 +- .../easytier-uptime/src/health_checker.rs | 5 +- easytier-gui/src-tauri/src/lib.rs | 12 ++- easytier/src/easytier-core.rs | 6 +- easytier/src/instance_manager.rs | 101 ++++++------------ easytier/src/launcher.rs | 18 +--- easytier/src/rpc_service/instance_manage.rs | 3 +- 8 files changed, 51 insertions(+), 102 deletions(-) diff --git a/easytier-contrib/easytier-ffi/src/lib.rs b/easytier-contrib/easytier-ffi/src/lib.rs index e63b97f2..098e5f33 100644 --- a/easytier-contrib/easytier-ffi/src/lib.rs +++ b/easytier-contrib/easytier-ffi/src/lib.rs @@ -4,7 +4,6 @@ use dashmap::DashMap; use easytier::{ common::config::{ConfigLoader as _, TomlConfigLoader}, instance_manager::NetworkInstanceManager, - launcher::ConfigSource, }; static INSTANCE_NAME_ID_MAP: once_cell::sync::Lazy> = @@ -129,7 +128,7 @@ pub unsafe extern "C" fn run_network_instance(cfg_str: *const std::ffi::c_char) return -1; } - let instance_id = match INSTANCE_MANAGER.run_network_instance(cfg, ConfigSource::FFI) { + let instance_id = match INSTANCE_MANAGER.run_network_instance(cfg, false) { Ok(id) => id, Err(e) => { set_error_msg(&format!("failed to start instance: {}", e)); diff --git a/easytier-contrib/easytier-ohrs/src/lib.rs b/easytier-contrib/easytier-ohrs/src/lib.rs index 40e83919..e6a1386f 100644 --- a/easytier-contrib/easytier-ohrs/src/lib.rs +++ b/easytier-contrib/easytier-ohrs/src/lib.rs @@ -3,7 +3,6 @@ mod native_log; use easytier::common::config::{ConfigLoader, TomlConfigLoader}; use easytier::common::constants::EASYTIER_VERSION; use easytier::instance_manager::NetworkInstanceManager; -use easytier::launcher::ConfigSource; use napi_derive_ohos::napi; use ohos_hilog_binding::{hilog_debug, hilog_error}; use std::format; @@ -76,9 +75,7 @@ pub fn run_network_instance(cfg_str: String) -> bool { { return false; } - INSTANCE_MANAGER - .run_network_instance(cfg, ConfigSource::FFI) - .unwrap(); + INSTANCE_MANAGER.run_network_instance(cfg, false).unwrap(); true } diff --git a/easytier-contrib/easytier-uptime/src/health_checker.rs b/easytier-contrib/easytier-uptime/src/health_checker.rs index 1d443446..ba6741c3 100644 --- a/easytier-contrib/easytier-uptime/src/health_checker.rs +++ b/easytier-contrib/easytier-uptime/src/health_checker.rs @@ -13,7 +13,6 @@ use easytier::{ }, defer, instance_manager::NetworkInstanceManager, - launcher::ConfigSource, }; use serde::{Deserialize, Serialize}; use sqlx::any; @@ -392,7 +391,7 @@ impl HealthChecker { .delete_network_instance(vec![cfg.get_id()]); }); self.instance_mgr - .run_network_instance(cfg.clone(), ConfigSource::FFI) + .run_network_instance(cfg.clone(), false) .with_context(|| "failed to run network instance")?; let now = Instant::now(); @@ -436,7 +435,7 @@ impl HealthChecker { ); self.instance_mgr - .run_network_instance(cfg.clone(), ConfigSource::Web) + .run_network_instance(cfg.clone(), true) .with_context(|| "failed to run network instance")?; self.inst_id_map.insert(node_id, cfg.get_id()); diff --git a/easytier-gui/src-tauri/src/lib.rs b/easytier-gui/src-tauri/src/lib.rs index 089a18d6..7ac43460 100644 --- a/easytier-gui/src-tauri/src/lib.rs +++ b/easytier-gui/src-tauri/src/lib.rs @@ -240,12 +240,16 @@ async fn get_config(app: AppHandle, instance_id: String) -> Result, enabled_networks: Vec) -> Result<(), String> { +async fn load_configs( + configs: Vec, + enabled_networks: Vec, +) -> Result<(), String> { CLIENT_MANAGER .get() .unwrap() .storage .load_configs(configs, enabled_networks) + .await .map_err(|e| e.to_string())?; Ok(()) } @@ -304,7 +308,7 @@ mod manager { use super::*; use async_trait::async_trait; use dashmap::{DashMap, DashSet}; - use easytier::launcher::{ConfigSource, NetworkConfig}; + use easytier::launcher::NetworkConfig; use easytier::proto::rpc_impl::bidirect::BidirectRpcManager; use easytier::proto::rpc_types::controller::BaseController; use easytier::rpc_service::remote_client::PersistentConfig; @@ -334,7 +338,7 @@ mod manager { } } - pub(super) fn load_configs( + pub(super) async fn load_configs( &self, configs: Vec, enabled_networks: Vec, @@ -363,7 +367,7 @@ mod manager { .get(&uuid) .map(|i| i.value().1.gen_config()) .ok_or_else(|| anyhow::anyhow!("Config not found"))??; - INSTANCE_MANAGER.run_network_instance(config, ConfigSource::GUI)?; + INSTANCE_MANAGER.run_network_instance(config, true)?; self.enabled_networks.insert(uuid); } } diff --git a/easytier/src/easytier-core.rs b/easytier/src/easytier-core.rs index 3e5af913..14930850 100644 --- a/easytier/src/easytier-core.rs +++ b/easytier/src/easytier-core.rs @@ -29,7 +29,7 @@ use easytier::{ connector::create_connector_by_url, defer, instance_manager::NetworkInstanceManager, - launcher::{add_proxy_network_to_config, ConfigSource}, + launcher::add_proxy_network_to_config, proto::common::{CompressionAlgoPb, NatType}, rpc_service::ApiRpcServer, tunnel::{IpVersion, PROTO_PORT_OFFSET}, @@ -1236,7 +1236,7 @@ async fn run_main(cli: Cli) -> anyhow::Result<()> { println!("############### TOML ###############\n"); println!("{}", cfg.dump()); println!("-----------------------------------"); - manager.run_network_instance(cfg, ConfigSource::File)?; + manager.run_network_instance(cfg, true)?; } } @@ -1249,7 +1249,7 @@ async fn run_main(cli: Cli) -> anyhow::Result<()> { println!("############### TOML ###############\n"); println!("{}", cfg.dump()); println!("-----------------------------------"); - manager.run_network_instance(cfg, ConfigSource::Cli)?; + manager.run_network_instance(cfg, true)?; } tokio::select! { diff --git a/easytier/src/instance_manager.rs b/easytier/src/instance_manager.rs index b8d07c5b..3ce9ad74 100644 --- a/easytier/src/instance_manager.rs +++ b/easytier/src/instance_manager.rs @@ -8,7 +8,7 @@ use crate::{ global_ctx::{EventBusSubscriber, GlobalCtxEvent}, scoped_task::ScopedTask, }, - launcher::{ConfigSource, NetworkInstance, NetworkInstanceRunningInfo}, + launcher::{NetworkInstance, NetworkInstanceRunningInfo}, proto::{self}, rpc_service::InstanceRpcService, }; @@ -37,32 +37,18 @@ impl NetworkInstanceManager { } fn start_instance_task(&self, instance_id: uuid::Uuid) -> Result<(), anyhow::Error> { + if tokio::runtime::Handle::try_current().is_err() { + return Err(anyhow::anyhow!( + "tokio runtime not found, cannot start instance task" + )); + } + let instance = self .instance_map .get(&instance_id) .ok_or_else(|| anyhow::anyhow!("instance {} not found", instance_id))?; - - match instance.get_config_source() { - ConfigSource::FFI | ConfigSource::GUI => { - // FFI and GUI have no tokio runtime, so we don't need to spawn a task - return Ok(()); - } - _ => { - if tokio::runtime::Handle::try_current().is_err() { - return Err(anyhow::anyhow!( - "tokio runtime not found, cannot start instance task" - )); - } - } - } - let instance_stop_notifier = instance.get_stop_notifier(); - let instance_event_receiver = match instance.get_config_source() { - ConfigSource::Cli | ConfigSource::File | ConfigSource::Web => { - Some(instance.subscribe_event()) - } - ConfigSource::GUI | ConfigSource::FFI => None, - }; + let instance_event_receiver = instance.subscribe_event(); let instance_map = self.instance_map.clone(); let instance_stop_tasks = self.instance_stop_tasks.clone(); @@ -76,7 +62,6 @@ impl NetworkInstanceManager { return; }; let _t = instance_event_receiver - .flatten() .map(|event| ScopedTask::from(handle_event(instance_id, event))); instance_stop_notifier.notified().await; if let Some(instance) = instance_map.get(&instance_id) { @@ -97,18 +82,20 @@ impl NetworkInstanceManager { pub fn run_network_instance( &self, cfg: TomlConfigLoader, - source: ConfigSource, + watch_event: bool, ) -> Result { let instance_id = cfg.get_id(); if self.instance_map.contains_key(&instance_id) { anyhow::bail!("instance {} already exists", instance_id); } - let mut instance = NetworkInstance::new(cfg, source); + let mut instance = NetworkInstance::new(cfg); instance.start()?; self.instance_map.insert(instance_id, instance); - self.start_instance_task(instance_id)?; + if watch_event { + self.start_instance_task(instance_id)?; + } Ok(instance_id) } @@ -429,32 +416,20 @@ mod tests { c.set_listeners(vec![format!("tcp://0.0.0.0:{}", port).parse().unwrap()]); }) .unwrap(), - ConfigSource::Cli, + true, ) .unwrap(); let instance_id2 = manager - .run_network_instance( - TomlConfigLoader::new_from_str(cfg_str).unwrap(), - ConfigSource::File, - ) + .run_network_instance(TomlConfigLoader::new_from_str(cfg_str).unwrap(), true) .unwrap(); let instance_id3 = manager - .run_network_instance( - TomlConfigLoader::new_from_str(cfg_str).unwrap(), - ConfigSource::GUI, - ) + .run_network_instance(TomlConfigLoader::new_from_str(cfg_str).unwrap(), false) .unwrap(); let instance_id4 = manager - .run_network_instance( - TomlConfigLoader::new_from_str(cfg_str).unwrap(), - ConfigSource::Web, - ) + .run_network_instance(TomlConfigLoader::new_from_str(cfg_str).unwrap(), true) .unwrap(); let instance_id5 = manager - .run_network_instance( - TomlConfigLoader::new_from_str(cfg_str).unwrap(), - ConfigSource::FFI, - ) + .run_network_instance(TomlConfigLoader::new_from_str(cfg_str).unwrap(), false) .unwrap(); tokio::time::sleep(std::time::Duration::from_secs(1)).await; // to make instance actually started @@ -489,16 +464,10 @@ mod tests { let port = crate::utils::find_free_tcp_port(10012..65534).expect("no free tcp port found"); assert!(manager - .run_network_instance( - TomlConfigLoader::new_from_str(cfg_str).unwrap(), - ConfigSource::Cli, - ) + .run_network_instance(TomlConfigLoader::new_from_str(cfg_str).unwrap(), true,) .is_err()); assert!(manager - .run_network_instance( - TomlConfigLoader::new_from_str(cfg_str).unwrap(), - ConfigSource::File, - ) + .run_network_instance(TomlConfigLoader::new_from_str(cfg_str).unwrap(), true,) .is_err()); assert!(manager .run_network_instance( @@ -507,20 +476,14 @@ mod tests { c.set_listeners(vec![format!("tcp://0.0.0.0:{}", port).parse().unwrap()]); }) .unwrap(), - ConfigSource::GUI, + false, ) .is_ok()); assert!(manager - .run_network_instance( - TomlConfigLoader::new_from_str(cfg_str).unwrap(), - ConfigSource::Web, - ) + .run_network_instance(TomlConfigLoader::new_from_str(cfg_str).unwrap(), true,) .is_err()); assert!(manager - .run_network_instance( - TomlConfigLoader::new_from_str(cfg_str).unwrap(), - ConfigSource::FFI, - ) + .run_network_instance(TomlConfigLoader::new_from_str(cfg_str).unwrap(), false,) .is_ok()); std::thread::sleep(std::time::Duration::from_secs(1)); // wait instance actually started @@ -546,7 +509,8 @@ mod tests { let free_tcp_port = crate::utils::find_free_tcp_port(10012..65534).expect("no free tcp port found"); - for config_source in [ConfigSource::Cli, ConfigSource::File] { + // Test with event watching enabled (for CLI/File/RPC usage) - instance should auto-stop on error + for watch_event in [true] { let _port_holder = std::net::TcpListener::bind(format!("0.0.0.0:{}", free_tcp_port)).unwrap(); @@ -561,7 +525,7 @@ mod tests { manager .run_network_instance( TomlConfigLoader::new_from_str(cfg_str.as_str()).unwrap(), - config_source.clone(), + watch_event, ) .unwrap(); @@ -570,11 +534,14 @@ mod tests { assert_eq!(manager.list_network_instance_ids().len(), 1); } _ = tokio::time::sleep(std::time::Duration::from_secs(5)) => { - panic!("instance manager with single failed instance({:?}) should not running", config_source); + panic!("instance manager with single failed instance({:?}) should not running", watch_event); } } } - for config_source in [ConfigSource::Web, ConfigSource::GUI, ConfigSource::FFI] { + + // Test without event watching (for FFI usage) - instance should remain even if failed + { + let watch_event = false; let _port_holder = std::net::TcpListener::bind(format!("0.0.0.0:{}", free_tcp_port)).unwrap(); @@ -589,7 +556,7 @@ mod tests { manager .run_network_instance( TomlConfigLoader::new_from_str(cfg_str.as_str()).unwrap(), - config_source.clone(), + watch_event, ) .unwrap(); @@ -616,7 +583,7 @@ mod tests { manager .run_network_instance( TomlConfigLoader::new_from_str(cfg_str.as_str()).unwrap(), - ConfigSource::Cli, + true, ) .unwrap(); @@ -625,7 +592,7 @@ mod tests { manager .run_network_instance( TomlConfigLoader::new_from_str(cfg_str.as_str()).unwrap(), - ConfigSource::Cli, + true, ) .unwrap(); diff --git a/easytier/src/launcher.rs b/easytier/src/launcher.rs index ffef59e1..52330a42 100644 --- a/easytier/src/launcher.rs +++ b/easytier/src/launcher.rs @@ -281,35 +281,19 @@ impl Drop for EasyTierLauncher { pub type NetworkInstanceRunningInfo = crate::proto::api::manage::NetworkInstanceRunningInfo; -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum ConfigSource { - Cli, - File, - Web, - GUI, - FFI, -} - pub struct NetworkInstance { config: TomlConfigLoader, launcher: Option, - - config_source: ConfigSource, } impl NetworkInstance { - pub fn new(config: TomlConfigLoader, source: ConfigSource) -> Self { + pub fn new(config: TomlConfigLoader) -> Self { Self { config, launcher: None, - config_source: source, } } - pub fn get_config_source(&self) -> ConfigSource { - self.config_source.clone() - } - pub fn is_easytier_running(&self) -> bool { self.launcher.is_some() && self.launcher.as_ref().unwrap().running() } diff --git a/easytier/src/rpc_service/instance_manage.rs b/easytier/src/rpc_service/instance_manage.rs index 9cab1f95..61ab21f2 100644 --- a/easytier/src/rpc_service/instance_manage.rs +++ b/easytier/src/rpc_service/instance_manage.rs @@ -3,7 +3,6 @@ use std::sync::Arc; use crate::{ common::config::ConfigLoader, instance_manager::NetworkInstanceManager, - launcher::ConfigSource, proto::{ api::manage::*, rpc_types::{self, controller::BaseController}, @@ -47,7 +46,7 @@ impl WebClientService for InstanceManageRpcService { if let Some(inst_id) = req.inst_id { cfg.set_id(inst_id.into()); } - self.manager.run_network_instance(cfg, ConfigSource::Web)?; + self.manager.run_network_instance(cfg, true)?; println!("instance {} started", id); Ok(RunNetworkInstanceResponse { inst_id: Some(id.into()),