fix: Mejorar robustez del endpoint de eliminación de apps

- unregister_app_handler ahora intenta eliminar de 3 fuentes:
  1. AppManager (memoria) - puede fallar si app no se registró bien
  2. JSON (soft delete) - marca como eliminada en monitored_apps.json
  3. systemd (físico) - elimina .service, stop, disable, daemon-reload
- Logs detallados en cada paso (INFO/WARNING)
- Ya no falla con 'Aplicación no encontrada' si solo falta en memoria
- Resuelve problema de GatewaySIGMA que no se podía eliminar
- Operación best-effort: intenta todo sin fallar si un paso falla
This commit is contained in:
2026-01-21 17:12:10 -05:00
parent 2f867cb7ed
commit d8b3214ede

View File

@@ -64,16 +64,63 @@ pub async fn unregister_app_handler(
State(state): State<Arc<ApiState>>,
Path(app_name): Path<String>,
) -> Result<Json<ApiResponse<OperationResponse>>, StatusCode> {
use crate::config::get_config_manager;
use crate::systemd::{SystemCtl, ServiceGenerator};
let logger = crate::logger::get_logger();
let service_name = format!("siax-app-{}.service", app_name);
logger.info("API", &format!("🗑️ Solicitud de eliminación para: {}", app_name));
// Intentar 1: Eliminar desde AppManager (si está en memoria)
let mut deleted_from_memory = false;
match state.app_manager.unregister_app(&app_name) {
Ok(_) => Ok(Json(ApiResponse::success(OperationResponse {
app_name: app_name.clone(),
operation: "unregister".to_string(),
success: true,
message: "Aplicación eliminada exitosamente".to_string(),
}))),
Err(e) => Ok(Json(ApiResponse::error(e.to_string()))),
Ok(_) => {
logger.info("API", &format!("✅ Eliminado desde AppManager: {}", app_name));
deleted_from_memory = true;
}
Err(e) => {
logger.warning("API", &format!("App no encontrada en AppManager: {}", e), None);
}
}
// Intentar 2: Soft delete en JSON (siempre intentar)
let config_manager = get_config_manager();
let delete_reason = Some("Eliminada desde el panel de control".to_string());
match config_manager.soft_delete_app(&app_name, delete_reason) {
Ok(_) => {
logger.info("API", &format!("✅ Soft delete en JSON: {}", app_name));
}
Err(e) => {
logger.warning("API", &format!("No se pudo hacer soft delete en JSON: {}", e), None);
}
}
// Intentar 3: Eliminar servicio systemd físicamente (siempre intentar)
let _ = SystemCtl::stop(&service_name);
logger.info("API", &format!("Deteniendo servicio: {}", service_name));
let _ = SystemCtl::disable(&service_name);
logger.info("API", &format!("Deshabilitando servicio: {}", service_name));
match ServiceGenerator::delete_service_file(&service_name) {
Ok(_) => {
logger.info("API", &format!("✅ Archivo .service eliminado: {}", service_name));
}
Err(e) => {
logger.warning("API", &format!("No se pudo eliminar .service: {}", e), None);
}
}
let _ = SystemCtl::daemon_reload();
logger.info("API", "🔄 daemon-reload ejecutado");
Ok(Json(ApiResponse::success(OperationResponse {
app_name: app_name.clone(),
operation: "unregister".to_string(),
success: true,
message: format!("Aplicación '{}' eliminada exitosamente (servicio systemd + soft delete en JSON)", app_name),
})))
}
pub async fn start_app_handler(