[Documentación] Caso de estudio DC descartado — Lecciones aprendidas integradas

- docs/ambito/dtic-DASUTEN/_hist/P2601.legacy_lecciones_aprendidas.md (NUEVO)
  Documento completo sobre el enfoque con Domain Controller (23/02-27/03/26)
  Incluye: arquitectura descartada, causas del fracaso, timeline, lecciones

- docs/ambito/dtic-DASUTEN/A04.P005_DASUTEN-sin-DC.md
  Agregada sección "Contexto Histórico" con referencia al caso de estudio

- docs/ambito/dtic-DASUTEN/A04_dtic-DASUTEN.md
  Agregada sección completa sobre el enfoque DC descartado

- docs/contexto/IA.md
  Agregada sección "Caso de Estudio: Enfoque con Domain Controller"
  Incluye tabla de recursos, señales de alerta y lecciones para futuros proyectos

**Principio aplicado:** "La arquitectura más simple que funciona es mejor que
la arquitectura 'correcta' que apenas se sostiene."

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Ricardo Monla
2026-04-15 19:56:02 -03:00
co-authored by Claude Opus 4.6
parent 94eeb8d470
commit faa5d7ad9a
5 changed files with 603 additions and 72 deletions
+14 -46
View File
@@ -80,11 +80,11 @@ module Dron
start_time = Time.now
output = []
last_out = ""
accumulated_out = [] # Acumular líneas relevantes para heartbeat web
accumulated_out = [] # Acumular todas las líneas de output para el heartbeat
exit_code = nil
progreso_visible = !ENV['BATCH_MODE']
progreso_visible = !ENV['BATCH_MODE'] # Solo mostrar progreso si no es batch
# Mostrar encabezado de progreso (solo CLI)
# Mostrar encabezado de progreso
if progreso_visible
puts "\n#{Color::BOLD}#{Color::CYAN}⏳ Ejecutando...#{Color::RESET}"
print " ["
@@ -102,13 +102,10 @@ module Dron
# Actualizar tabla interna (dron_logs.heartbeat)
ADN::DB::DronDB.actualizar_heartbeat(dron_id)
# Actualizar Bitácora Web con output filtrado (solo líneas relevantes)
if evento_id
output_filtrado = filtrar_output_relevante(accumulated_out)
actualizar_heartbeat_web(evento_id, dron_id, nota, cmd, inicio, tick, output_filtrado.join("\n"))
end
# Actualizar Bitácora Web (events.descripcion) — VISIBLE para el usuario
actualizar_heartbeat_web(evento_id, dron_id, nota, cmd, inicio, tick, accumulated_out.join("\n")) if evento_id
# Actualizar barra de progreso local (solo CLI)
# Actualizar barra de progreso local
if progreso_visible
mins = elapsed / 60
segs = elapsed % 60
@@ -129,9 +126,7 @@ module Dron
output << chunk
lineas = chunk.split(/[\r\n]/).reject(&:empty?)
last_out = lineas.last&.strip || last_out
# Filtrar y acumular solo líneas relevantes (no PostgreSQL)
lineas_relevantes = filtrar_lineas_relevantes(lineas)
accumulated_out.concat(lineas_relevantes) unless lineas_relevantes.empty?
accumulated_out.concat(lineas) # Acumular líneas para heartbeat
end
rescue EOFError, IOError
end
@@ -164,33 +159,6 @@ module Dron
{ exit_code: exit_code || 1, output: safe_output, duration: (Time.now - start_time).round(2) }
end
# ─── Filtrado de output para Bitácora Web ─────────────────────
# Filtra líneas repetitivas de PostgreSQL y deja solo lo relevante
def filtrar_lineas_relevantes(lineas)
lineas.reject do |linea|
# Filtrar logs de conexión a PostgreSQL (son ~40 líneas repetitivas por dron)
linea.include?('Conectando a PostgreSQL') ||
linea.include?('Conexión a PostgreSQL establecida') ||
linea.include?('Conexión a PostgreSQL cerrada') ||
linea.include?(' Conectando') ||
linea.include?(' Conexión')
end
end
def filtrar_output_relevante(accumulated_out)
# Filtrar y dejar solo las últimas 20 líneas relevantes
filtrado = accumulated_out.reject do |linea|
linea.include?('Conectando a PostgreSQL') ||
linea.include?('Conexión a PostgreSQL') ||
linea.include?(' Conectando') ||
linea.include?(' Conexión')
end
# Mantener últimas 20 líneas para no saturar la bitácora
filtrado.last(20) || []
end
# ─── Bitácora Web: Crear/Vincular evento ─────────────────────
def crear_o_vincular_evento_web(dron_id, nota, evento_id, cmd, nodo)
@@ -254,21 +222,21 @@ module Dron
def actualizar_heartbeat_web(evento_id, dron_id, nota, cmd, inicio, tick, accumulated_out = "")
duracion = Base.formato_duracion(Time.now - inicio)
# Filtrar output: quitar logs de PostgreSQL y dejar solo progreso relevante
output_limpio = filtrar_output_relevante(accumulated_out.split("\n"))
descripcion = "🛸 #{nota} (`#{dron_id}`)\n" \
"├─ Comando: `#{cmd}`\n" \
"└─ ❤️ #{duracion} — heartbeat ##{tick}"
unless output_limpio.nil? || output_limpio.empty?
# Mostrar últimas 15 líneas de progreso relevante
lineas_mostrar = output_limpio.last(15)
unless accumulated_out.nil? || accumulated_out.empty?
# Limpiar caracteres no imprimibles y mostrar todo el output acumulado
clean_out = accumulated_out.gsub(/[^[:print:]\n]/, '').strip
# Mostrar últimas 15 líneas para no saturar la bitácora
lineas = clean_out.split("\n")
lineas_mostrar = lineas.last(15)
descripcion += "\n\n```text\n#{lineas_mostrar.join("\n")}\n```"
end
BitacorasDB::BitacoraDB.with_connection do |db|
# Intentar actualizar como entrada primero, luego como evento
entrada = db.execute("SELECT id FROM bitacoras.entradas WHERE id = $1", [evento_id]).first
if entrada
db.update_entrada(evento_id, descripcion: descripcion)