feat: Agregar campo id (UUID v4) a MonitoredApp
Cada app registrada ahora tiene un identificador único UUID v4. Se agrega la dependencia uuid al proyecto y se asegura que todas las rutas de creación de MonitoredApp generen un id único. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,10 +2,15 @@ use serde::{Serialize, Deserialize};
|
||||
use std::fs::{self, create_dir_all};
|
||||
use std::path::Path;
|
||||
use std::sync::{Arc, RwLock, OnceLock};
|
||||
use uuid::Uuid;
|
||||
use crate::logger::get_logger;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct MonitoredApp {
|
||||
/// ID único de la aplicación (UUID v4)
|
||||
#[serde(default = "generate_uuid")]
|
||||
pub id: String,
|
||||
|
||||
/// Nombre de la aplicación
|
||||
pub name: String,
|
||||
|
||||
@@ -70,6 +75,10 @@ pub struct MonitoredApp {
|
||||
pub created_at: Option<String>,
|
||||
}
|
||||
|
||||
fn generate_uuid() -> String {
|
||||
Uuid::new_v4().to_string()
|
||||
}
|
||||
|
||||
fn default_mode() -> String {
|
||||
"production".to_string()
|
||||
}
|
||||
@@ -186,14 +195,20 @@ impl ConfigManager {
|
||||
}
|
||||
|
||||
/// Agrega una app con información completa
|
||||
pub fn add_app_full(&self, app: MonitoredApp) -> Result<(), String> {
|
||||
pub fn add_app_full(&self, mut app: MonitoredApp) -> Result<(), String> {
|
||||
let mut config = self.config.write().unwrap();
|
||||
|
||||
// Verificar si ya existe
|
||||
if config.apps.iter().any(|a| a.name == app.name) {
|
||||
// Verificar si ya existe una app ACTIVA con el mismo nombre
|
||||
// (las apps eliminadas no cuentan, pueden tener el mismo nombre)
|
||||
if config.apps.iter().any(|a| a.name == app.name && !a.deleted) {
|
||||
return Err(format!("La app '{}' ya está siendo monitoreada", app.name));
|
||||
}
|
||||
|
||||
// Asegurar que tenga un UUID único
|
||||
if app.id.is_empty() {
|
||||
app.id = Uuid::new_v4().to_string();
|
||||
}
|
||||
|
||||
config.apps.push(app);
|
||||
|
||||
// Guardar en disco
|
||||
@@ -210,6 +225,7 @@ impl ConfigManager {
|
||||
let registered_at = chrono::Local::now().to_rfc3339();
|
||||
|
||||
let app = MonitoredApp {
|
||||
id: Uuid::new_v4().to_string(),
|
||||
name,
|
||||
service_name,
|
||||
path: String::new(),
|
||||
@@ -231,6 +247,45 @@ impl ConfigManager {
|
||||
self.add_app_full(app)
|
||||
}
|
||||
|
||||
/// Actualiza una app existente (sin crear duplicados)
|
||||
pub fn update_app(&self, name: &str, updated_app: MonitoredApp) -> Result<(), String> {
|
||||
let mut config = self.config.write().unwrap();
|
||||
|
||||
// Buscar la app activa con ese nombre
|
||||
let app = config.apps.iter_mut().find(|a| a.name == name && !a.deleted);
|
||||
|
||||
match app {
|
||||
Some(app) => {
|
||||
// Preservar el ID original y la fecha de registro
|
||||
let original_id = app.id.clone();
|
||||
let original_registered_at = app.registered_at.clone();
|
||||
|
||||
// Actualizar todos los campos
|
||||
app.name = updated_app.name;
|
||||
app.service_name = updated_app.service_name;
|
||||
app.path = updated_app.path;
|
||||
app.port = updated_app.port;
|
||||
app.entry_point = updated_app.entry_point;
|
||||
app.node_bin = updated_app.node_bin;
|
||||
app.mode = updated_app.mode;
|
||||
app.user = updated_app.user;
|
||||
app.service_file_path = updated_app.service_file_path;
|
||||
app.environment = updated_app.environment;
|
||||
|
||||
// Mantener el ID original y fecha de registro
|
||||
app.id = original_id;
|
||||
app.registered_at = original_registered_at;
|
||||
|
||||
// Guardar en disco
|
||||
match Self::save_config_to_file(&self.config_path, &config) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) => Err(format!("Error al guardar configuración: {}", e))
|
||||
}
|
||||
}
|
||||
None => Err(format!("La app '{}' no se encontró", name))
|
||||
}
|
||||
}
|
||||
|
||||
/// Realiza un soft delete: marca la app como eliminada pero mantiene el registro
|
||||
pub fn soft_delete_app(&self, name: &str, reason: Option<String>) -> Result<(), String> {
|
||||
let mut config = self.config.write().unwrap();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/// Módulo para descubrir servicios systemd existentes
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use uuid::Uuid;
|
||||
use crate::logger::get_logger;
|
||||
use crate::config::{get_config_manager, MonitoredApp};
|
||||
|
||||
@@ -232,7 +233,8 @@ pub fn sync_discovered_services(services: Vec<DiscoveredService>) {
|
||||
detect_port_from_name(&service.app_name)
|
||||
});
|
||||
|
||||
// Verificar si ya existe en la configuración
|
||||
// Verificar si ya existe una app ACTIVA en la configuración
|
||||
// (get_apps() ya filtra las eliminadas, así que esto está bien)
|
||||
let existing_apps = config_manager.get_apps();
|
||||
let already_exists = existing_apps.iter().any(|app| app.name == service.app_name);
|
||||
|
||||
@@ -248,6 +250,7 @@ pub fn sync_discovered_services(services: Vec<DiscoveredService>) {
|
||||
let registered_at = chrono::Local::now().to_rfc3339();
|
||||
|
||||
let app = MonitoredApp {
|
||||
id: Uuid::new_v4().to_string(),
|
||||
name: service.app_name.clone(),
|
||||
service_name,
|
||||
path: service.working_directory.unwrap_or_default(),
|
||||
|
||||
@@ -5,6 +5,7 @@ use crate::logger::get_logger;
|
||||
use crate::config::{get_config_manager, MonitoredApp};
|
||||
use dashmap::DashMap;
|
||||
use std::sync::Arc;
|
||||
use uuid::Uuid;
|
||||
|
||||
pub struct AppManager {
|
||||
apps: Arc<DashMap<String, ServiceConfig>>,
|
||||
@@ -79,6 +80,7 @@ impl AppManager {
|
||||
.unwrap_or_else(|| "production".to_string());
|
||||
|
||||
let monitored_app = MonitoredApp {
|
||||
id: Uuid::new_v4().to_string(),
|
||||
name: config.app_name.clone(),
|
||||
service_name: config.service_name(),
|
||||
path: config.working_directory.clone(),
|
||||
|
||||
Reference in New Issue
Block a user