[MEJORA] Salida visual mejorada para pipelines DASUTEN
Se implementó mejora en la salida de comandos para hacerla más intuitiva: Cambios realizados: - bkps.rb: Encabezado y cierre visual con box drawing para tareas DASUTEN - ejecutor.rb: Barra de progreso con timer en tiempo real durante ejecución - A04.P006: Actualizado con resultados del test completo 2026-04-15 Nueva salida visual: - Encabezado con contexto del pipeline (nombre, hora de inicio) - Timer en vivo durante la ejecución ([1m 23s] ejecutando...) - Cierre con estado (✅/❌) y duración total Resultados del test completo (Pipeline FULL): - 6 pasos completados exitosamente en 13m 15s - DBCC CHECKDB: Integridad OK - Todos los drones atómicos funcionaron correctamente Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
4a0cdd883e
commit
db86f86e59
+27
-2
@@ -750,7 +750,21 @@ module ADN
|
|||||||
end
|
end
|
||||||
|
|
||||||
t_inicio = Time.now
|
t_inicio = Time.now
|
||||||
@logger.info("▶ #{tarea[:texto]} (#{tipo})")
|
|
||||||
|
# Encabezado visual para tareas DASUTEN
|
||||||
|
es_dasuten = (tipo == 'dasuten')
|
||||||
|
if es_dasuten
|
||||||
|
puts ""
|
||||||
|
puts "╔═══════════════════════════════════════════════════════════╗"
|
||||||
|
puts "║ 🔄 Pipeline DASUTEN — #{tarea[:texto].ljust(35)} ║"
|
||||||
|
puts "╠═══════════════════════════════════════════════════════════╣"
|
||||||
|
puts "║ Inicio: #{Time.now.strftime('%H:%M:%S')}".ljust(55) + "║"
|
||||||
|
puts "╚═══════════════════════════════════════════════════════════╝"
|
||||||
|
puts ""
|
||||||
|
else
|
||||||
|
@logger.info("▶ #{tarea[:texto]} (#{tipo})")
|
||||||
|
end
|
||||||
|
|
||||||
procesador = factory.call(@logger)
|
procesador = factory.call(@logger)
|
||||||
|
|
||||||
# Modo atómico: procesar un solo archivo
|
# Modo atómico: procesar un solo archivo
|
||||||
@@ -764,7 +778,18 @@ module ADN
|
|||||||
duracion = (Time.now - t_inicio).to_i
|
duracion = (Time.now - t_inicio).to_i
|
||||||
mins = duracion / 60
|
mins = duracion / 60
|
||||||
segs = duracion % 60
|
segs = duracion % 60
|
||||||
@logger.info("✔ #{tarea[:texto]} — #{mins}m#{segs}s")
|
|
||||||
|
if es_dasuten
|
||||||
|
estado = resultado ? "✅ Completado" : "❌ Fallido"
|
||||||
|
puts ""
|
||||||
|
puts "╔═══════════════════════════════════════════════════════════╗"
|
||||||
|
puts "║ #{estado} — Duración: #{mins}m #{segs}s".ljust(55) + "║"
|
||||||
|
puts "╚═══════════════════════════════════════════════════════════╝"
|
||||||
|
puts ""
|
||||||
|
else
|
||||||
|
@logger.info("✔ #{tarea[:texto]} — #{mins}m#{segs}s")
|
||||||
|
end
|
||||||
|
|
||||||
resultado
|
resultado
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
require_relative 'base'
|
require_relative 'base'
|
||||||
require_relative '../../db/core/dron_db'
|
require_relative '../../db/core/dron_db'
|
||||||
|
require_relative '../../core/colores'
|
||||||
require 'open3'
|
require 'open3'
|
||||||
require 'timeout'
|
require 'timeout'
|
||||||
require 'time'
|
require 'time'
|
||||||
@@ -81,19 +82,36 @@ module Dron
|
|||||||
last_out = ""
|
last_out = ""
|
||||||
accumulated_out = [] # Acumular todas las líneas de output para el heartbeat
|
accumulated_out = [] # Acumular todas las líneas de output para el heartbeat
|
||||||
exit_code = nil
|
exit_code = nil
|
||||||
|
progreso_visible = !ENV['BATCH_MODE'] # Solo mostrar progreso si no es batch
|
||||||
|
|
||||||
|
# Mostrar encabezado de progreso
|
||||||
|
if progreso_visible
|
||||||
|
puts "\n#{Color::BOLD}#{Color::CYAN}⏳ Ejecutando...#{Color::RESET}"
|
||||||
|
print " ["
|
||||||
|
$stdout.flush
|
||||||
|
end
|
||||||
|
|
||||||
heartbeat_thread = Thread.new do
|
heartbeat_thread = Thread.new do
|
||||||
tick = 0
|
tick = 0
|
||||||
|
start = Time.now
|
||||||
loop do
|
loop do
|
||||||
sleep(HEARTBEAT_INTERVAL)
|
sleep(HEARTBEAT_INTERVAL)
|
||||||
tick += 1
|
tick += 1
|
||||||
|
elapsed = (Time.now - start).to_i
|
||||||
|
|
||||||
# Actualizar tabla interna (dron_logs.heartbeat)
|
# Actualizar tabla interna (dron_logs.heartbeat)
|
||||||
ADN::DB::DronDB.actualizar_heartbeat(dron_id)
|
ADN::DB::DronDB.actualizar_heartbeat(dron_id)
|
||||||
|
|
||||||
# Actualizar Bitácora Web (events.descripcion) — VISIBLE para el usuario
|
# Actualizar Bitácora Web (events.descripcion) — VISIBLE para el usuario
|
||||||
# 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
|
actualizar_heartbeat_web(evento_id, dron_id, nota, cmd, inicio, tick, accumulated_out.join("\n")) if evento_id
|
||||||
|
|
||||||
|
# Actualizar barra de progreso local
|
||||||
|
if progreso_visible
|
||||||
|
mins = elapsed / 60
|
||||||
|
segs = elapsed % 60
|
||||||
|
print "\r [#{Color::CYAN}#{mins}m #{segs}s#{Color::RESET}] ejecutando..."
|
||||||
|
$stdout.flush
|
||||||
|
end
|
||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
Base.logger.warn("⚠️ Error en heartbeat ##{tick}: #{e.message}")
|
Base.logger.warn("⚠️ Error en heartbeat ##{tick}: #{e.message}")
|
||||||
end
|
end
|
||||||
@@ -129,6 +147,13 @@ module Dron
|
|||||||
heartbeat_thread.exit
|
heartbeat_thread.exit
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Finalizar barra de progreso
|
||||||
|
if progreso_visible
|
||||||
|
estado = exit_code == 0 ? "#{Color::GREEN}✅#{Color::RESET}" : "#{Color::RED}❌#{Color::RESET}"
|
||||||
|
print "\r #{estado} "
|
||||||
|
puts "#{Color::BOLD}Completado en #{Base.formato_duracion(Time.now - start_time)}#{Color::RESET}"
|
||||||
|
end
|
||||||
|
|
||||||
raw_output = output.join("\n").strip
|
raw_output = output.join("\n").strip
|
||||||
safe_output = raw_output.dup.force_encoding('UTF-8').scrub('?')
|
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) }
|
{ exit_code: exit_code || 1, output: safe_output, duration: (Time.now - start_time).round(2) }
|
||||||
|
|||||||
@@ -18,6 +18,15 @@
|
|||||||
| **Fase 3: Pipeline Diferencial** | ✅ Completado | 100% |
|
| **Fase 3: Pipeline Diferencial** | ✅ Completado | 100% |
|
||||||
| **Fase 4: Integración BKPs** | ✅ Completado | 100% |
|
| **Fase 4: Integración BKPs** | ✅ Completado | 100% |
|
||||||
| **Fase 5: Mejora de Latidos** | ✅ Completado | 100% |
|
| **Fase 5: Mejora de Latidos** | ✅ Completado | 100% |
|
||||||
|
| **Fase 6: Validación Pipeline FULL** | ✅ Completado | 100% |
|
||||||
|
|
||||||
|
### Resumen de Validación (2026-04-15)
|
||||||
|
|
||||||
|
✅ **Pipeline COMPLETO validado de principio a fin**
|
||||||
|
- Backup FULL exportado, transferido, subido, bajado, restaurado y verificado
|
||||||
|
- Integridad de BD confirmada con DBCC CHECKDB: **OK**
|
||||||
|
- Duración total: **13m 15s** (dentro de lo estimado: ~35-40 min)
|
||||||
|
- Todos los drones atómicos funcionaron correctamente en modo orquestado
|
||||||
|
|
||||||
## 🎯 Objetivo
|
## 🎯 Objetivo
|
||||||
|
|
||||||
@@ -181,6 +190,79 @@ El procesador `Dasuten` fue integrado en `bkps.rb` como un nuevo tipo de tarea:
|
|||||||
| 2026-04-14 15:54 | Completo | 44.8s | 1.33 GB | ✅ |
|
| 2026-04-14 15:54 | Completo | 44.8s | 1.33 GB | ✅ |
|
||||||
| 2026-04-14 16:03 | Diferencial | 2.44s | 0.39 MB | ✅ |
|
| 2026-04-14 16:03 | Diferencial | 2.44s | 0.39 MB | ✅ |
|
||||||
| 2026-04-14 16:35 | Upload Drive | 23.79s | 0.39 MB | ✅ |
|
| 2026-04-14 16:35 | Upload Drive | 23.79s | 0.39 MB | ✅ |
|
||||||
|
| **2026-04-15 11:01** | **Pipeline FULL** | **13m 15s** | **~1.3 GB** | **✅ COMPLETO** |
|
||||||
|
|
||||||
|
### Detalle Pipeline 2026-04-15 (Test Completo)
|
||||||
|
|
||||||
|
| Paso | Tarea | Nodo | Duración | Estado |
|
||||||
|
|------|-------|------|----------|--------|
|
||||||
|
| 1 | `dasuten_export_full` | srvv-fenix | 46s | ✅ |
|
||||||
|
| 2 | `dasuten_transferir` | srv-ns8 | 2s | ✅ |
|
||||||
|
| 3 | `dasuten_upload` | srv-ns8 | 7m 9s | ✅ |
|
||||||
|
| 4 | `dasuten_download` | dasu-sql4 | 52s | ✅ |
|
||||||
|
| 5 | `dasuten_restaurar_full` | dasu-sql4 | 13s | ✅ |
|
||||||
|
| 6 | `dasuten_verificar` | dasu-sql4 | 4m 11s | ✅ |
|
||||||
|
|
||||||
|
**Throughput:**
|
||||||
|
- Upload a Drive: ~3 MB/s (limitado por ancho de banda de subida)
|
||||||
|
- Download desde Drive: ~25 MB/s (HTTP directo)
|
||||||
|
- Restore SQL: instantáneo (MOVE de archivos)
|
||||||
|
- DBCC CHECKDB: ~1.2M páginas verificadas en 4m 11s
|
||||||
|
|
||||||
|
## 🧪 Sesión de Test Completa (2026-04-15)
|
||||||
|
|
||||||
|
**Objetivo:** Validar el pipeline completo de backup/restore usando **backup FULL** (no diferencial).
|
||||||
|
|
||||||
|
### Ejecución Orquestada (REINICIADA)
|
||||||
|
|
||||||
|
Se utiliza el comando **orquestado** `dasuten_full` que ejecuta los 6 pasos en secuencia automáticamente.
|
||||||
|
|
||||||
|
| Paso | ID Tarea | Dron | Nodo | Estado | Duración |
|
||||||
|
|------|----------|------|------|--------|----------|
|
||||||
|
| **1** | `dasuten_export_full` | `dasuten_exportar_srvv-fenix.rb` | srvv-fenix | ⏳ Pendiente | — |
|
||||||
|
| **2** | `dasuten_transferir` | `dasuten_transferir_srvv-fenix-srv-ns8.rb` | srv-ns8 | ⏳ Pendiente | — |
|
||||||
|
| **3** | `dasuten_upload` | `dasuten_upload_srv-ns8-drive.rb` | srv-ns8 | ⏳ Pendiente | — |
|
||||||
|
| **4** | `dasuten_download` | `dasuten_download_drive-dasu-sql4.rb` | dasu-sql4 | ⏳ Pendiente | — |
|
||||||
|
| **5** | `dasuten_restaurar_full` | `dasuten_restaurar_dasu-sql4.rb` | dasu-sql4 | ⏳ Pendiente | — |
|
||||||
|
| **6** | `dasuten_verificar` | `dasuten_verificar-integridad_dasu-sql4.rb` | dasu-sql4 | ⏳ Pendiente | — |
|
||||||
|
|
||||||
|
**Comando orquestado:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Ejecución completa (6 pasos en secuencia)
|
||||||
|
./adn/tools/run bkps run dasuten_full --batch
|
||||||
|
```
|
||||||
|
|
||||||
|
**Notas de la sesión:**
|
||||||
|
- Tipo de backup: **FULL/COMPLETO** (~1.3 GB esperado)
|
||||||
|
- Ejecución: **Orquestada** (un solo comando, 6 pasos automáticos)
|
||||||
|
- Heartbeats acumulados: Se prueba la nueva mejora de latidos que muestra las últimas 15 líneas del progreso en Bitácora Web
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Registro de Ejecución — Test 2026-04-15
|
||||||
|
|
||||||
|
| Hora | Paso | Resultado | Duración | Observaciones |
|
||||||
|
|------|------|-----------|----------|---------------|
|
||||||
|
| 11:01 | 🚩 **TEST INICIADO** | — | — | Pipeline FULL orquestado (`dasuten_full --batch`) |
|
||||||
|
| 11:01 | 1. Exportar | ✅ Completado | 46s | Backup FULL en `X:\` (srvv-fenix) |
|
||||||
|
| 11:02 | 2. Transferir | ✅ Completado | 2s | SMB: fenix → ns8 (`/var/tmp/`) |
|
||||||
|
| 11:02 | 3. Upload | ✅ Completado | 7m 9s | rclone: ns8 → Google Drive (~1.3 GB) |
|
||||||
|
| 11:09 | 4. Download | ✅ Completado | 52s | HTTP: Drive → dasu-sql4 (`F:\BACKUP\`) |
|
||||||
|
| 11:10 | 5. Restore | ✅ Completado | 13s | RESTORE DATABASE WITH REPLACE + MOVE |
|
||||||
|
| 11:10 | 6. Verificar | ✅ Completado | 4m 11s | DBCC CHECKDB — Integridad: **OK** |
|
||||||
|
| 11:14 | 🏁 **PIPELINE COMPLETADO** | ✅ | **13m 15s** | Todos los pasos exitosos |
|
||||||
|
|
||||||
|
**Resultados clave:**
|
||||||
|
- ✅ Backup FULL de ~1.3 GB transferido correctamente
|
||||||
|
- ✅ Google Drive como intermediario (sin dependencia de Tailscale)
|
||||||
|
- ✅ Restore completado con MOVE a `F:\DATA` y `F:\LOG`
|
||||||
|
- ✅ DBCC CHECKDB: **Integridad OK** (base de datos consistente)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Ejecuciones anteriores (descartadas):**
|
||||||
|
- Paso 4 (Restore diferencial): ✅ 14.7s — ejecutado de forma aislada, no corresponde a esta sesión FULL
|
||||||
|
|
||||||
## ⚠️ Consideraciones Técnicas
|
## ⚠️ Consideraciones Técnicas
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user