From 9ddeca254300f81046caaf85fa50cac8968d3ccb Mon Sep 17 00:00:00 2001 From: Reboot-Codes Date: Thu, 1 May 2025 09:35:04 -0700 Subject: [PATCH] Add de-init logic for modules --- clover-hub/src/server/modman/mod.rs | 34 ++---- clover-hub/src/server/modman/modules.rs | 144 +++++++++++++++++++++++- 2 files changed, 153 insertions(+), 25 deletions(-) diff --git a/clover-hub/src/server/modman/mod.rs b/clover-hub/src/server/modman/mod.rs index 13b8912..b364909 100644 --- a/clover-hub/src/server/modman/mod.rs +++ b/clover-hub/src/server/modman/mod.rs @@ -4,7 +4,6 @@ pub mod ipc; pub mod models; pub mod modules; -use crate::server::modman::modules::init_module; use ipc::handle_ipc_msg; use log::{ debug, @@ -14,6 +13,10 @@ use models::{ ModManStore, Module, }; +use modules::{ + deinit_module, + init_module, +}; use nexus::{ arbiter::models::ApiKeyWithoutUID, server::models::UserConfig, @@ -55,13 +58,8 @@ pub async fn modman_main( if modules.len() > 0 { // Initialize modules that were registered already via configuration and persistence. for (id, module) in modules.iter() { - info!( - "Initializing pre configured module: {}:\n type: {}\n name: {}", - id.clone(), - module.module_type.clone(), - module.get_name() - ); - let _components_initialized = init_module(&init_store, id.clone(), module.clone()).await; + let (initialized, _components_initialized) = + init_module(&init_store, id.clone(), module.clone()).await; } } else { info!("No pre-configured modules to initialize."); @@ -95,31 +93,19 @@ pub async fn modman_main( // Clean up all modules on shutdown. info!("Cleaning up modules..."); + // TODO: Add override cancellation token to force stop! + tokio::select! { modules = store.modules.lock() => { debug!("done waiting for lock"); if modules.len() > 0 { for (id, module) in modules.iter() { if module.initialized { - info!("De-initializing configured module: {}:\n type: {}\n name: {}", id.clone(), module.module_type.clone(), module.get_name()); - // let (de_initialized, _components_de_initialized) = deinit_module(&store, id.clone(), module.clone()).await; - let de_initialized = true; - - // Update the store with new state of the module. - if de_initialized { - store.modules.lock().await.insert(id.clone(), Module { - module_type: module.module_type.clone(), - module_name: module.module_name.clone(), - custom_name: module.custom_name.clone(), - initialized: false, - components: module.components.clone(), - registered_by: module.registered_by.clone() - }); - } + let (de_initialized, _components_deinitialized) = deinit_module(&store, id.clone(), module.clone()).await; } } } else { - debug!("No modules to de-init."); + debug!("No modules to deinit."); } } } diff --git a/clover-hub/src/server/modman/modules.rs b/clover-hub/src/server/modman/modules.rs index 9215e16..2ed7db4 100644 --- a/clover-hub/src/server/modman/modules.rs +++ b/clover-hub/src/server/modman/modules.rs @@ -16,6 +16,13 @@ pub async fn init_module(store: &ModManStore, id: String, module: Module) -> (bo let mut initialized_module = module.initialized; let mut initialized_module_components = 0; + info!( + "Initializing module: {}:\n type: {}\n name: {}", + id.clone(), + module.module_type.clone(), + module.get_name() + ); + if !initialized_module { if module.components.len() == 0 { warn!( @@ -142,4 +149,139 @@ pub async fn init_module(store: &ModManStore, id: String, module: Module) -> (bo (initialized_module, initialized_module_components) } -// TODO: deinit_module(); impl! +pub async fn deinit_module(store: &ModManStore, id: String, module: Module) -> (bool, usize) { + let mut initialized_module = module.initialized; + let mut deinitialized_module_components = 0; + + info!( + "De-initializing module: {}:\n type: {}\n name: {}", + id.clone(), + module.module_type.clone(), + module.get_name() + ); + + if initialized_module { + if module.components.len() == 0 { + warn!( + "Module: {}, does not have any components, skipping.", + id.clone() + ); + initialized_module = false; + } else { + let mut critical_failiure = None; + + for (component_id, component_arc) in module.components.iter() { + let component_arc_binding = component_arc.clone(); + let component_guard = component_arc_binding.lock().await; + let (component_meta, mut component) = ( + component_guard.clone().0.clone(), + component_guard.clone().1.clone(), + ); + + if component_meta.critical { + info!( + "Module: {}, deinitalizing CRITICAL component: {}...", + id.clone(), + component_id.clone() + ); + } else { + info!( + "Module: {}, deinitalizing component: {}...", + id.clone(), + component_id.clone() + ); + } + + let component_deinitalized = match component.deinit(Arc::new(store.clone())).await { + Ok(_) => true, + Err(e) => { + error!( + "Failed to deinitalize component \"{}\", due to: {}", + component_id.clone(), + e + ); + false + } + }; + + if component_deinitalized { + info!( + "Module: {}, successfully deinitalized component: {}!", + id.clone(), + component_id.clone() + ); + deinitialized_module_components += 1; + } else { + if component_meta.critical { + critical_failiure = Some(component_id.clone()); + } else { + warn!( + "Module: {}, failed to deinitialize component: {}!", + id.clone(), + component_id.clone() + ); + } + } + + match critical_failiure { + Some(_) => { + break; + } + None => {} + } + + std::mem::drop(component_guard); + } + + match critical_failiure { + Some(component_id) => { + error!( + "Module: {}, failed to deinitalize critical component: {}!", + id.clone(), + component_id.clone() + ); + } + None => { + if deinitialized_module_components != module.components.len() { + if deinitialized_module_components > 0 { + warn!( + "Module: {}, only deinitialized {} out of {} components!", + id.clone(), + deinitialized_module_components, + module.components.len() + ); + initialized_module = true; + } else { + error!("Module: {}, failed to deinitialize!", id.clone()); + } + } + } + } + } + } + + if !initialized_module { + // Update the store with new state of the module. + if !initialized_module { + store.modules.lock().await.insert( + id.clone(), + Module { + module_type: module.module_type.clone(), + module_name: module.module_name.clone(), + custom_name: module.custom_name.clone(), + initialized: false, + components: module.components.clone(), + registered_by: module.registered_by.clone(), + }, + ); + + info!( + "Module: {} ({}), Deinitialized!", + module.get_name(), + id.clone() + ); + } + } + + (initialized_module, deinitialized_module_components) +} -- 2.51.2