feat(dron): Migración a AtomicDrones con arquitectura DB-First
Implementación del sistema AtomicDrones basado en "Menos es Más": - Refactorización de dron.rb a dispatcher + módulos atómicos - Nuevos módulos: ejecutor, vigilante, sanador, bitacora - DronDB para acceso a datos en PostgreSQL - Tablas: dron_logs, dron_avances, dron_metricas - Views: vw_dron_estado, vw_dron_zombies, vw_dron_metricas_semanal - Health check con detección de zombies (heartbeat > 5min) - Dashboard compacto de la flota - Saneamiento con reintentos (backoff exponencial) y limpieza Comandos soportados: - dron lanzar: Ejecutar comando como dron - dron flota: Dashboard de la flota - dron salud: Health check activo - dron estado <ID>: Estado detallado - dron sanear: Saneamiento completo - dron limpiar: Limpieza de antiguos - dron reintentar: Re-intentar fallidos Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
b5e89144e3
commit
3543e62263
@@ -0,0 +1,177 @@
|
||||
-- Migración 003: Tablas para sistema de Drones (AtomicDrones)
|
||||
-- Fecha: 2026-04-07
|
||||
-- Propósito: Crear tablas internas para registro detallado de drones
|
||||
|
||||
-- ============================================================================
|
||||
-- Tabla 1: dron_logs - Logs detallados de cada dron
|
||||
-- ============================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS bitacoras.dron_logs (
|
||||
id SERIAL PRIMARY KEY,
|
||||
dron_id VARCHAR(50) NOT NULL, -- ej: dron_083045_123
|
||||
flujo_id VARCHAR(50), -- ID de orquestación (si aplica)
|
||||
tipo VARCHAR(20) NOT NULL, -- ejecutor|vigilante|sanador|planificador|mensajero|orquestador
|
||||
estado VARCHAR(20) NOT NULL, -- pending|running|completed|failed|zombie
|
||||
cmd TEXT, -- Comando ejecutado
|
||||
output TEXT, -- Salida del comando
|
||||
exit_code INTEGER, -- Código de retorno
|
||||
started_at TIMESTAMP DEFAULT NOW(),
|
||||
completed_at TIMESTAMP,
|
||||
heartbeat TIMESTAMP DEFAULT NOW(), -- Último heartbeat
|
||||
reintentos INTEGER DEFAULT 0,
|
||||
metadata JSONB DEFAULT '{}'::jsonb, -- Metadata adicional
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Índices para consultas eficientes
|
||||
CREATE INDEX IF NOT EXISTS idx_dron_logs_estado ON bitacoras.dron_logs(estado);
|
||||
CREATE INDEX IF NOT EXISTS idx_dron_logs_heartbeat ON bitacoras.dron_logs(heartbeat);
|
||||
CREATE INDEX IF NOT EXISTS idx_dron_logs_flujo ON bitacoras.dron_logs(flujo_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_dron_logs_tipo ON bitacoras.dron_logs(tipo);
|
||||
CREATE INDEX IF NOT EXISTS idx_dron_logs_started_at ON bitacoras.dron_logs(started_at);
|
||||
|
||||
-- ============================================================================
|
||||
-- Tabla 2: dron_avances - Avances paso-a-paso (para flujos multi-paso)
|
||||
-- ============================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS bitacoras.dron_avances (
|
||||
id SERIAL PRIMARY KEY,
|
||||
dron_id VARCHAR(50) NOT NULL,
|
||||
flujo_id VARCHAR(50), -- ID de orquestación
|
||||
paso INTEGER NOT NULL, -- Número de paso en flujo
|
||||
descripcion TEXT NOT NULL, -- Qué se está haciendo
|
||||
estado VARCHAR(20) NOT NULL, -- pending|running|completed|failed
|
||||
output TEXT, -- Salida del paso
|
||||
started_at TIMESTAMP DEFAULT NOW(),
|
||||
completed_at TIMESTAMP,
|
||||
metadata JSONB DEFAULT '{}'::jsonb,
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Índices para consultas eficientes
|
||||
CREATE INDEX IF NOT EXISTS idx_dron_avances_dron ON bitacoras.dron_avances(dron_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_dron_avances_flujo ON bitacoras.dron_avances(flujo_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_dron_avances_paso ON bitacoras.dron_avances(paso);
|
||||
|
||||
-- ============================================================================
|
||||
-- Tabla 3: dron_metricas - Métricas de rendimiento (agregaciones diarias)
|
||||
-- ============================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS bitacoras.dron_metricas (
|
||||
id SERIAL PRIMARY KEY,
|
||||
fecha DATE NOT NULL,
|
||||
dron_tipo VARCHAR(20) NOT NULL,
|
||||
total_ejecuciones INTEGER DEFAULT 0,
|
||||
completados INTEGER DEFAULT 0,
|
||||
fallidos INTEGER DEFAULT 0,
|
||||
zombies INTEGER DEFAULT 0,
|
||||
tiempo_promedio INTERVAL DEFAULT '0 seconds',
|
||||
reintentos_total INTEGER DEFAULT 0,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW(),
|
||||
UNIQUE(fecha, dron_tipo)
|
||||
);
|
||||
|
||||
-- Índice para consultas por fecha
|
||||
CREATE INDEX IF NOT EXISTS idx_dron_metricas_fecha ON bitacoras.dron_metricas(fecha);
|
||||
|
||||
-- ============================================================================
|
||||
-- Trigger: Actualizar updated_at automáticamente
|
||||
-- ============================================================================
|
||||
|
||||
-- Función para actualizar updated_at
|
||||
CREATE OR REPLACE FUNCTION bitacoras.update_updated_at_column()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = NOW();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
-- Trigger para dron_logs
|
||||
DROP TRIGGER IF EXISTS update_dron_logs_updated_at ON bitacoras.dron_logs;
|
||||
CREATE TRIGGER update_dron_logs_updated_at
|
||||
BEFORE UPDATE ON bitacoras.dron_logs
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION bitacoras.update_updated_at_column();
|
||||
|
||||
-- Trigger para dron_metricas
|
||||
DROP TRIGGER IF EXISTS update_dron_metricas_updated_at ON bitacoras.dron_metricas;
|
||||
CREATE TRIGGER update_dron_metricas_updated_at
|
||||
BEFORE UPDATE ON bitacoras.dron_metricas
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION bitacoras.update_updated_at_column();
|
||||
|
||||
-- ============================================================================
|
||||
-- Comentario de documentación
|
||||
-- ============================================================================
|
||||
|
||||
COMMENT ON TABLE bitacoras.dron_logs IS 'Logs detallados de cada dron en la colonia (NO visible directamente en Bitácora Web)';
|
||||
COMMENT ON TABLE bitacoras.dron_avances IS 'Avances paso-a-paso de flujos multi-paso (orquestación)';
|
||||
COMMENT ON TABLE bitacoras.dron_metricas IS 'Métricas agregadas diarias por tipo de dron (para dashboard y estadísticas)';
|
||||
|
||||
COMMENT ON COLUMN bitacoras.dron_logs.dron_id IS 'Identificador único del dron (ej: dron_083045_123)';
|
||||
COMMENT ON COLUMN bitacoras.dron_logs.flujo_id IS 'ID de orquestación para agrupar drones de un mismo flujo';
|
||||
COMMENT ON COLUMN bitacoras.dron_logs.tipo IS 'Tipo de dron: ejecutor, vigilante, sanador, planificador, mensajero, orquestador';
|
||||
COMMENT ON COLUMN bitacoras.dron_logs.estado IS 'Estado actual: pending, running, completed, failed, zombie';
|
||||
COMMENT ON COLUMN bitacoras.dron_logs.heartbeat IS 'Último heartbeat - si > 5min, dron se considera zombie';
|
||||
|
||||
-- ============================================================================
|
||||
-- Vistas útiles para consultas frecuentes
|
||||
-- ============================================================================
|
||||
|
||||
-- Vista: Drones activos por estado
|
||||
CREATE OR REPLACE VIEW bitacoras.vw_dron_estado AS
|
||||
SELECT
|
||||
estado,
|
||||
tipo,
|
||||
COUNT(*) as cantidad,
|
||||
MIN(started_at) as mas_antiguo,
|
||||
MAX(started_at) as mas_reciente
|
||||
FROM bitacoras.dron_logs
|
||||
WHERE estado IN ('running', 'pending')
|
||||
GROUP BY estado, tipo;
|
||||
|
||||
-- Vista: Drones zombies (heartbeat > 5min)
|
||||
CREATE OR REPLACE VIEW bitacoras.vw_dron_zombies AS
|
||||
SELECT
|
||||
id,
|
||||
dron_id,
|
||||
tipo,
|
||||
cmd,
|
||||
started_at,
|
||||
heartbeat,
|
||||
EXTRACT(EPOCH FROM (NOW() - heartbeat))/60 as minutos_sin_heartbeat
|
||||
FROM bitacoras.dron_logs
|
||||
WHERE estado = 'running'
|
||||
AND heartbeat < NOW() - INTERVAL '5 minutes';
|
||||
|
||||
-- Vista: Métricas de los últimos 7 días
|
||||
CREATE OR REPLACE VIEW bitacoras.vw_dron_metricas_semanal AS
|
||||
SELECT
|
||||
fecha,
|
||||
dron_tipo,
|
||||
total_ejecuciones,
|
||||
completados,
|
||||
fallidos,
|
||||
zombies,
|
||||
tiempo_promedio,
|
||||
reintentos_total,
|
||||
ROUND(100.0 * completados / NULLIF(total_ejecuciones, 0), 2) as tasa_exito
|
||||
FROM bitacoras.dron_metricas
|
||||
WHERE fecha >= CURRENT_DATE - INTERVAL '7 days'
|
||||
ORDER BY fecha DESC, dron_tipo;
|
||||
|
||||
-- ============================================================================
|
||||
-- Mensaje de confirmación
|
||||
-- ============================================================================
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
RAISE NOTICE '✅ Migración 003 completada: Tablas de Drones creadas exitosamente';
|
||||
RAISE NOTICE ' - bitacoras.dron_logs: Logs detallados';
|
||||
RAISE NOTICE ' - bitacoras.dron_avances: Avances paso-a-paso';
|
||||
RAISE NOTICE ' - bitacoras.dron_metricas: Métricas agregadas';
|
||||
RAISE NOTICE ' - Vistas: vw_dron_estado, vw_dron_zombies, vw_dron_metricas_semanal';
|
||||
END $$;
|
||||
Reference in New Issue
Block a user