refactor: replace ConfigSource with bool parameter (#1516)

This commit is contained in:
Mg Pig
2025-11-04 13:48:10 +08:00
committed by GitHub
parent 6bb2fd9a15
commit 89cc75f674
8 changed files with 51 additions and 102 deletions

View File

@@ -4,7 +4,6 @@ use dashmap::DashMap;
use easytier::{ use easytier::{
common::config::{ConfigLoader as _, TomlConfigLoader}, common::config::{ConfigLoader as _, TomlConfigLoader},
instance_manager::NetworkInstanceManager, instance_manager::NetworkInstanceManager,
launcher::ConfigSource,
}; };
static INSTANCE_NAME_ID_MAP: once_cell::sync::Lazy<DashMap<String, uuid::Uuid>> = static INSTANCE_NAME_ID_MAP: once_cell::sync::Lazy<DashMap<String, uuid::Uuid>> =
@@ -129,7 +128,7 @@ pub unsafe extern "C" fn run_network_instance(cfg_str: *const std::ffi::c_char)
return -1; 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, Ok(id) => id,
Err(e) => { Err(e) => {
set_error_msg(&format!("failed to start instance: {}", e)); set_error_msg(&format!("failed to start instance: {}", e));

View File

@@ -3,7 +3,6 @@ mod native_log;
use easytier::common::config::{ConfigLoader, TomlConfigLoader}; use easytier::common::config::{ConfigLoader, TomlConfigLoader};
use easytier::common::constants::EASYTIER_VERSION; use easytier::common::constants::EASYTIER_VERSION;
use easytier::instance_manager::NetworkInstanceManager; use easytier::instance_manager::NetworkInstanceManager;
use easytier::launcher::ConfigSource;
use napi_derive_ohos::napi; use napi_derive_ohos::napi;
use ohos_hilog_binding::{hilog_debug, hilog_error}; use ohos_hilog_binding::{hilog_debug, hilog_error};
use std::format; use std::format;
@@ -76,9 +75,7 @@ pub fn run_network_instance(cfg_str: String) -> bool {
{ {
return false; return false;
} }
INSTANCE_MANAGER INSTANCE_MANAGER.run_network_instance(cfg, false).unwrap();
.run_network_instance(cfg, ConfigSource::FFI)
.unwrap();
true true
} }

View File

@@ -13,7 +13,6 @@ use easytier::{
}, },
defer, defer,
instance_manager::NetworkInstanceManager, instance_manager::NetworkInstanceManager,
launcher::ConfigSource,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sqlx::any; use sqlx::any;
@@ -392,7 +391,7 @@ impl HealthChecker {
.delete_network_instance(vec![cfg.get_id()]); .delete_network_instance(vec![cfg.get_id()]);
}); });
self.instance_mgr self.instance_mgr
.run_network_instance(cfg.clone(), ConfigSource::FFI) .run_network_instance(cfg.clone(), false)
.with_context(|| "failed to run network instance")?; .with_context(|| "failed to run network instance")?;
let now = Instant::now(); let now = Instant::now();
@@ -436,7 +435,7 @@ impl HealthChecker {
); );
self.instance_mgr self.instance_mgr
.run_network_instance(cfg.clone(), ConfigSource::Web) .run_network_instance(cfg.clone(), true)
.with_context(|| "failed to run network instance")?; .with_context(|| "failed to run network instance")?;
self.inst_id_map.insert(node_id, cfg.get_id()); self.inst_id_map.insert(node_id, cfg.get_id());

View File

@@ -240,12 +240,16 @@ async fn get_config(app: AppHandle, instance_id: String) -> Result<NetworkConfig
} }
#[tauri::command] #[tauri::command]
fn load_configs(configs: Vec<NetworkConfig>, enabled_networks: Vec<String>) -> Result<(), String> { async fn load_configs(
configs: Vec<NetworkConfig>,
enabled_networks: Vec<String>,
) -> Result<(), String> {
CLIENT_MANAGER CLIENT_MANAGER
.get() .get()
.unwrap() .unwrap()
.storage .storage
.load_configs(configs, enabled_networks) .load_configs(configs, enabled_networks)
.await
.map_err(|e| e.to_string())?; .map_err(|e| e.to_string())?;
Ok(()) Ok(())
} }
@@ -304,7 +308,7 @@ mod manager {
use super::*; use super::*;
use async_trait::async_trait; use async_trait::async_trait;
use dashmap::{DashMap, DashSet}; use dashmap::{DashMap, DashSet};
use easytier::launcher::{ConfigSource, NetworkConfig}; use easytier::launcher::NetworkConfig;
use easytier::proto::rpc_impl::bidirect::BidirectRpcManager; use easytier::proto::rpc_impl::bidirect::BidirectRpcManager;
use easytier::proto::rpc_types::controller::BaseController; use easytier::proto::rpc_types::controller::BaseController;
use easytier::rpc_service::remote_client::PersistentConfig; 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, &self,
configs: Vec<NetworkConfig>, configs: Vec<NetworkConfig>,
enabled_networks: Vec<String>, enabled_networks: Vec<String>,
@@ -363,7 +367,7 @@ mod manager {
.get(&uuid) .get(&uuid)
.map(|i| i.value().1.gen_config()) .map(|i| i.value().1.gen_config())
.ok_or_else(|| anyhow::anyhow!("Config not found"))??; .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); self.enabled_networks.insert(uuid);
} }
} }

View File

@@ -29,7 +29,7 @@ use easytier::{
connector::create_connector_by_url, connector::create_connector_by_url,
defer, defer,
instance_manager::NetworkInstanceManager, instance_manager::NetworkInstanceManager,
launcher::{add_proxy_network_to_config, ConfigSource}, launcher::add_proxy_network_to_config,
proto::common::{CompressionAlgoPb, NatType}, proto::common::{CompressionAlgoPb, NatType},
rpc_service::ApiRpcServer, rpc_service::ApiRpcServer,
tunnel::{IpVersion, PROTO_PORT_OFFSET}, tunnel::{IpVersion, PROTO_PORT_OFFSET},
@@ -1236,7 +1236,7 @@ async fn run_main(cli: Cli) -> anyhow::Result<()> {
println!("############### TOML ###############\n"); println!("############### TOML ###############\n");
println!("{}", cfg.dump()); println!("{}", cfg.dump());
println!("-----------------------------------"); 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!("############### TOML ###############\n");
println!("{}", cfg.dump()); println!("{}", cfg.dump());
println!("-----------------------------------"); println!("-----------------------------------");
manager.run_network_instance(cfg, ConfigSource::Cli)?; manager.run_network_instance(cfg, true)?;
} }
tokio::select! { tokio::select! {

View File

@@ -8,7 +8,7 @@ use crate::{
global_ctx::{EventBusSubscriber, GlobalCtxEvent}, global_ctx::{EventBusSubscriber, GlobalCtxEvent},
scoped_task::ScopedTask, scoped_task::ScopedTask,
}, },
launcher::{ConfigSource, NetworkInstance, NetworkInstanceRunningInfo}, launcher::{NetworkInstance, NetworkInstanceRunningInfo},
proto::{self}, proto::{self},
rpc_service::InstanceRpcService, rpc_service::InstanceRpcService,
}; };
@@ -37,32 +37,18 @@ impl NetworkInstanceManager {
} }
fn start_instance_task(&self, instance_id: uuid::Uuid) -> Result<(), anyhow::Error> { 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 let instance = self
.instance_map .instance_map
.get(&instance_id) .get(&instance_id)
.ok_or_else(|| anyhow::anyhow!("instance {} not found", 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_stop_notifier = instance.get_stop_notifier();
let instance_event_receiver = match instance.get_config_source() { let instance_event_receiver = instance.subscribe_event();
ConfigSource::Cli | ConfigSource::File | ConfigSource::Web => {
Some(instance.subscribe_event())
}
ConfigSource::GUI | ConfigSource::FFI => None,
};
let instance_map = self.instance_map.clone(); let instance_map = self.instance_map.clone();
let instance_stop_tasks = self.instance_stop_tasks.clone(); let instance_stop_tasks = self.instance_stop_tasks.clone();
@@ -76,7 +62,6 @@ impl NetworkInstanceManager {
return; return;
}; };
let _t = instance_event_receiver let _t = instance_event_receiver
.flatten()
.map(|event| ScopedTask::from(handle_event(instance_id, event))); .map(|event| ScopedTask::from(handle_event(instance_id, event)));
instance_stop_notifier.notified().await; instance_stop_notifier.notified().await;
if let Some(instance) = instance_map.get(&instance_id) { if let Some(instance) = instance_map.get(&instance_id) {
@@ -97,18 +82,20 @@ impl NetworkInstanceManager {
pub fn run_network_instance( pub fn run_network_instance(
&self, &self,
cfg: TomlConfigLoader, cfg: TomlConfigLoader,
source: ConfigSource, watch_event: bool,
) -> Result<uuid::Uuid, anyhow::Error> { ) -> Result<uuid::Uuid, anyhow::Error> {
let instance_id = cfg.get_id(); let instance_id = cfg.get_id();
if self.instance_map.contains_key(&instance_id) { if self.instance_map.contains_key(&instance_id) {
anyhow::bail!("instance {} already exists", instance_id); anyhow::bail!("instance {} already exists", instance_id);
} }
let mut instance = NetworkInstance::new(cfg, source); let mut instance = NetworkInstance::new(cfg);
instance.start()?; instance.start()?;
self.instance_map.insert(instance_id, instance); 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) Ok(instance_id)
} }
@@ -429,32 +416,20 @@ mod tests {
c.set_listeners(vec![format!("tcp://0.0.0.0:{}", port).parse().unwrap()]); c.set_listeners(vec![format!("tcp://0.0.0.0:{}", port).parse().unwrap()]);
}) })
.unwrap(), .unwrap(),
ConfigSource::Cli, true,
) )
.unwrap(); .unwrap();
let instance_id2 = manager let instance_id2 = manager
.run_network_instance( .run_network_instance(TomlConfigLoader::new_from_str(cfg_str).unwrap(), true)
TomlConfigLoader::new_from_str(cfg_str).unwrap(),
ConfigSource::File,
)
.unwrap(); .unwrap();
let instance_id3 = manager let instance_id3 = manager
.run_network_instance( .run_network_instance(TomlConfigLoader::new_from_str(cfg_str).unwrap(), false)
TomlConfigLoader::new_from_str(cfg_str).unwrap(),
ConfigSource::GUI,
)
.unwrap(); .unwrap();
let instance_id4 = manager let instance_id4 = manager
.run_network_instance( .run_network_instance(TomlConfigLoader::new_from_str(cfg_str).unwrap(), true)
TomlConfigLoader::new_from_str(cfg_str).unwrap(),
ConfigSource::Web,
)
.unwrap(); .unwrap();
let instance_id5 = manager let instance_id5 = manager
.run_network_instance( .run_network_instance(TomlConfigLoader::new_from_str(cfg_str).unwrap(), false)
TomlConfigLoader::new_from_str(cfg_str).unwrap(),
ConfigSource::FFI,
)
.unwrap(); .unwrap();
tokio::time::sleep(std::time::Duration::from_secs(1)).await; // to make instance actually started 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"); let port = crate::utils::find_free_tcp_port(10012..65534).expect("no free tcp port found");
assert!(manager assert!(manager
.run_network_instance( .run_network_instance(TomlConfigLoader::new_from_str(cfg_str).unwrap(), true,)
TomlConfigLoader::new_from_str(cfg_str).unwrap(),
ConfigSource::Cli,
)
.is_err()); .is_err());
assert!(manager assert!(manager
.run_network_instance( .run_network_instance(TomlConfigLoader::new_from_str(cfg_str).unwrap(), true,)
TomlConfigLoader::new_from_str(cfg_str).unwrap(),
ConfigSource::File,
)
.is_err()); .is_err());
assert!(manager assert!(manager
.run_network_instance( .run_network_instance(
@@ -507,20 +476,14 @@ mod tests {
c.set_listeners(vec![format!("tcp://0.0.0.0:{}", port).parse().unwrap()]); c.set_listeners(vec![format!("tcp://0.0.0.0:{}", port).parse().unwrap()]);
}) })
.unwrap(), .unwrap(),
ConfigSource::GUI, false,
) )
.is_ok()); .is_ok());
assert!(manager assert!(manager
.run_network_instance( .run_network_instance(TomlConfigLoader::new_from_str(cfg_str).unwrap(), true,)
TomlConfigLoader::new_from_str(cfg_str).unwrap(),
ConfigSource::Web,
)
.is_err()); .is_err());
assert!(manager assert!(manager
.run_network_instance( .run_network_instance(TomlConfigLoader::new_from_str(cfg_str).unwrap(), false,)
TomlConfigLoader::new_from_str(cfg_str).unwrap(),
ConfigSource::FFI,
)
.is_ok()); .is_ok());
std::thread::sleep(std::time::Duration::from_secs(1)); // wait instance actually started std::thread::sleep(std::time::Duration::from_secs(1)); // wait instance actually started
@@ -546,7 +509,8 @@ mod tests {
let free_tcp_port = let free_tcp_port =
crate::utils::find_free_tcp_port(10012..65534).expect("no free tcp port found"); 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 = let _port_holder =
std::net::TcpListener::bind(format!("0.0.0.0:{}", free_tcp_port)).unwrap(); std::net::TcpListener::bind(format!("0.0.0.0:{}", free_tcp_port)).unwrap();
@@ -561,7 +525,7 @@ mod tests {
manager manager
.run_network_instance( .run_network_instance(
TomlConfigLoader::new_from_str(cfg_str.as_str()).unwrap(), TomlConfigLoader::new_from_str(cfg_str.as_str()).unwrap(),
config_source.clone(), watch_event,
) )
.unwrap(); .unwrap();
@@ -570,11 +534,14 @@ mod tests {
assert_eq!(manager.list_network_instance_ids().len(), 1); assert_eq!(manager.list_network_instance_ids().len(), 1);
} }
_ = tokio::time::sleep(std::time::Duration::from_secs(5)) => { _ = 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 = let _port_holder =
std::net::TcpListener::bind(format!("0.0.0.0:{}", free_tcp_port)).unwrap(); std::net::TcpListener::bind(format!("0.0.0.0:{}", free_tcp_port)).unwrap();
@@ -589,7 +556,7 @@ mod tests {
manager manager
.run_network_instance( .run_network_instance(
TomlConfigLoader::new_from_str(cfg_str.as_str()).unwrap(), TomlConfigLoader::new_from_str(cfg_str.as_str()).unwrap(),
config_source.clone(), watch_event,
) )
.unwrap(); .unwrap();
@@ -616,7 +583,7 @@ mod tests {
manager manager
.run_network_instance( .run_network_instance(
TomlConfigLoader::new_from_str(cfg_str.as_str()).unwrap(), TomlConfigLoader::new_from_str(cfg_str.as_str()).unwrap(),
ConfigSource::Cli, true,
) )
.unwrap(); .unwrap();
@@ -625,7 +592,7 @@ mod tests {
manager manager
.run_network_instance( .run_network_instance(
TomlConfigLoader::new_from_str(cfg_str.as_str()).unwrap(), TomlConfigLoader::new_from_str(cfg_str.as_str()).unwrap(),
ConfigSource::Cli, true,
) )
.unwrap(); .unwrap();

View File

@@ -281,35 +281,19 @@ impl Drop for EasyTierLauncher {
pub type NetworkInstanceRunningInfo = crate::proto::api::manage::NetworkInstanceRunningInfo; pub type NetworkInstanceRunningInfo = crate::proto::api::manage::NetworkInstanceRunningInfo;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ConfigSource {
Cli,
File,
Web,
GUI,
FFI,
}
pub struct NetworkInstance { pub struct NetworkInstance {
config: TomlConfigLoader, config: TomlConfigLoader,
launcher: Option<EasyTierLauncher>, launcher: Option<EasyTierLauncher>,
config_source: ConfigSource,
} }
impl NetworkInstance { impl NetworkInstance {
pub fn new(config: TomlConfigLoader, source: ConfigSource) -> Self { pub fn new(config: TomlConfigLoader) -> Self {
Self { Self {
config, config,
launcher: None, launcher: None,
config_source: source,
} }
} }
pub fn get_config_source(&self) -> ConfigSource {
self.config_source.clone()
}
pub fn is_easytier_running(&self) -> bool { pub fn is_easytier_running(&self) -> bool {
self.launcher.is_some() && self.launcher.as_ref().unwrap().running() self.launcher.is_some() && self.launcher.as_ref().unwrap().running()
} }

View File

@@ -3,7 +3,6 @@ use std::sync::Arc;
use crate::{ use crate::{
common::config::ConfigLoader, common::config::ConfigLoader,
instance_manager::NetworkInstanceManager, instance_manager::NetworkInstanceManager,
launcher::ConfigSource,
proto::{ proto::{
api::manage::*, api::manage::*,
rpc_types::{self, controller::BaseController}, rpc_types::{self, controller::BaseController},
@@ -47,7 +46,7 @@ impl WebClientService for InstanceManageRpcService {
if let Some(inst_id) = req.inst_id { if let Some(inst_id) = req.inst_id {
cfg.set_id(inst_id.into()); 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); println!("instance {} started", id);
Ok(RunNetworkInstanceResponse { Ok(RunNetworkInstanceResponse {
inst_id: Some(id.into()), inst_id: Some(id.into()),