use super::{Result, OrchestratorError}; use crate::models::{ServiceConfig, ManagedApp, AppStatus}; use crate::systemd::{ServiceGenerator, SystemCtl}; use crate::logger::get_logger; use dashmap::DashMap; use std::sync::Arc; pub struct AppManager { apps: Arc>, } impl AppManager { pub fn new() -> Self { AppManager { apps: Arc::new(DashMap::new()), } } pub fn register_app(&self, config: ServiceConfig) -> Result<()> { let logger = get_logger(); // Validar configuración config.validate() .map_err(|e| OrchestratorError::ValidationError(e))?; // Verificar si ya existe if self.apps.contains_key(&config.app_name) { logger.warning("AppManager", "Aplicación ya registrada", Some(&config.app_name)); return Err(OrchestratorError::AppAlreadyExists(config.app_name.clone())); } // Verificar si el servicio ya existe en systemd if SystemCtl::is_service_exists(&config.service_name()) { logger.warning("AppManager", "Servicio systemd ya existe", Some(&config.service_name())); return Err(OrchestratorError::AppAlreadyExists( format!("El servicio {} ya existe en systemd", config.service_name()) )); } logger.info("AppManager", &format!("Registrando aplicación: {}", config.app_name)); // Generar archivo de servicio let service_content = ServiceGenerator::create_service(&config)?; ServiceGenerator::write_service_file(&config, &service_content)?; // Recargar daemon de systemd SystemCtl::daemon_reload()?; // Habilitar el servicio SystemCtl::enable(&config.service_name())?; // Guardar en memoria self.apps.insert(config.app_name.clone(), config.clone()); logger.info("AppManager", &format!("Aplicación {} registrada exitosamente", config.app_name)); Ok(()) } pub fn unregister_app(&self, app_name: &str) -> Result<()> { let logger = get_logger(); logger.info("AppManager", &format!("Desregistrando aplicación: {}", app_name)); // Obtener configuración let config = self.apps.get(app_name) .ok_or_else(|| OrchestratorError::AppNotFound(app_name.to_string()))?; let service_name = config.service_name(); drop(config); // Liberar el lock // Detener el servicio si está corriendo let _ = SystemCtl::stop(&service_name); // Deshabilitar el servicio let _ = SystemCtl::disable(&service_name); // Eliminar archivo de servicio ServiceGenerator::delete_service_file(&service_name)?; // Recargar daemon SystemCtl::daemon_reload()?; // Eliminar de memoria self.apps.remove(app_name); logger.info("AppManager", &format!("Aplicación {} desregistrada exitosamente", app_name)); Ok(()) } pub fn list_apps(&self) -> Vec { self.apps.iter() .map(|entry| entry.key().clone()) .collect() } pub fn get_app(&self, app_name: &str) -> Option { self.apps.get(app_name).map(|entry| entry.clone()) } pub fn app_exists(&self, app_name: &str) -> bool { self.apps.contains_key(app_name) } pub fn get_app_status(&self, app_name: &str) -> Option { let config = self.get_app(app_name)?; let systemd_status = SystemCtl::status(&config.service_name()); // Por ahora retornamos información básica // El monitor.rs se encargará de enriquecer con PID, CPU, RAM Some(ManagedApp { name: app_name.to_string(), status: AppStatus::reconcile(false, &systemd_status), pid: None, cpu_usage: 0.0, memory_usage: 0, systemd_status, last_updated: chrono::Local::now().format("%Y-%m-%d %H:%M:%S").to_string(), }) } } impl Default for AppManager { fn default() -> Self { Self::new() } }