[DRON] Heartbeat con output acumulado en Bitácora Web
Mejora en el sistema de latidos de los drones para mostrar el progreso acumulado en lugar de solo la última línea. Cambios realizados: - ejecutor.rb: Acumulación de output en array accumulated_out[] - actualizar_heartbeat_web(): Muestra últimas 15 líneas en bloque ```text - A01.P009: Documentada Fase F1.5b con ejemplo técnico - A04.P006: Actualizado plan DASUTEN con mejora y lección aprendida Beneficio: Visibilidad completa del progreso de drones multi-paso (ej: [1/3], [2/3], [3/3] en pipelines de backup/restore) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
1bc6c94f78
commit
4a0cdd883e
@@ -78,6 +78,8 @@ module Dron
|
||||
def ejecutar_comando(cmd, dron_id, timeout, evento_id, nota, inicio)
|
||||
start_time = Time.now
|
||||
output = []
|
||||
last_out = ""
|
||||
accumulated_out = [] # Acumular todas las líneas de output para el heartbeat
|
||||
exit_code = nil
|
||||
|
||||
heartbeat_thread = Thread.new do
|
||||
@@ -90,7 +92,8 @@ module Dron
|
||||
ADN::DB::DronDB.actualizar_heartbeat(dron_id)
|
||||
|
||||
# Actualizar Bitácora Web (events.descripcion) — VISIBLE para el usuario
|
||||
actualizar_heartbeat_web(evento_id, dron_id, nota, cmd, inicio, tick) if evento_id
|
||||
# Pasamos el output acumulado para mostrar todo el progreso
|
||||
actualizar_heartbeat_web(evento_id, dron_id, nota, cmd, inicio, tick, accumulated_out.join("\n")) if evento_id
|
||||
rescue StandardError => e
|
||||
Base.logger.warn("⚠️ Error en heartbeat ##{tick}: #{e.message}")
|
||||
end
|
||||
@@ -99,7 +102,17 @@ module Dron
|
||||
begin
|
||||
Timeout.timeout(timeout) do
|
||||
Open3.popen3(cmd) do |_stdin, stdout, stderr, wait_thr|
|
||||
out_thread = Thread.new { output << stdout.read }
|
||||
out_thread = Thread.new do
|
||||
begin
|
||||
while chunk = stdout.readpartial(1024)
|
||||
output << chunk
|
||||
lineas = chunk.split(/[\r\n]/).reject(&:empty?)
|
||||
last_out = lineas.last&.strip || last_out
|
||||
accumulated_out.concat(lineas) # Acumular líneas para heartbeat
|
||||
end
|
||||
rescue EOFError, IOError
|
||||
end
|
||||
end
|
||||
err_thread = Thread.new { output << stderr.read }
|
||||
out_thread.join
|
||||
err_thread.join
|
||||
@@ -116,7 +129,9 @@ module Dron
|
||||
heartbeat_thread.exit
|
||||
end
|
||||
|
||||
{ exit_code: exit_code || 1, output: output.join("\n").strip, duration: (Time.now - start_time).round(2) }
|
||||
raw_output = output.join("\n").strip
|
||||
safe_output = raw_output.dup.force_encoding('UTF-8').scrub('?')
|
||||
{ exit_code: exit_code || 1, output: safe_output, duration: (Time.now - start_time).round(2) }
|
||||
end
|
||||
|
||||
# ─── Bitácora Web: Crear/Vincular evento ─────────────────────
|
||||
@@ -180,12 +195,21 @@ module Dron
|
||||
|
||||
# ─── Bitácora Web: Heartbeat visible ─────────────────────────
|
||||
|
||||
def actualizar_heartbeat_web(evento_id, dron_id, nota, cmd, inicio, tick)
|
||||
def actualizar_heartbeat_web(evento_id, dron_id, nota, cmd, inicio, tick, accumulated_out = "")
|
||||
duracion = Base.formato_duracion(Time.now - inicio)
|
||||
descripcion = "🛸 #{nota} (`#{dron_id}`)\n" \
|
||||
"├─ Comando: `#{cmd}`\n" \
|
||||
"└─ ❤️ #{duracion} — heartbeat ##{tick}"
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user