🐝 F2.T2: Condicionales --on-error abort|continue|retry
- abort: detiene al primer fallo (default) - continue: salta el fallo y sigue con el siguiente - retry: reintenta N veces antes de abortar (--retries N) - Resumen final con conteo de éxitos/fallos/saltados
This commit is contained in:
+50
-8
@@ -767,11 +767,13 @@ module ADN
|
||||
# ─── Orquestador: 1 dron por archivo ──────────────────────────
|
||||
|
||||
def cmd_orquestar(args)
|
||||
options = {}
|
||||
options = { on_error: 'abort', retries: 2 }
|
||||
OptionParser.new do |opts|
|
||||
opts.banner = "Uso: ./adn/tools/run bkps orquestar <T1|ID> [opciones]"
|
||||
opts.on("--timeout N", Integer, "Timeout por dron en segundos (default: 7200)") { |t| options[:timeout] = t }
|
||||
opts.on("--dry-run", "Solo listar archivos sin lanzar drones") { options[:dry_run] = true }
|
||||
opts.on("--on-error MODE", %w[abort continue retry], "Qué hacer si un dron falla (abort|continue|retry, default: abort)") { |m| options[:on_error] = m }
|
||||
opts.on("--retries N", Integer, "Número de reintentos si --on-error retry (default: 2)") { |n| options[:retries] = n }
|
||||
end.parse!(args)
|
||||
|
||||
ref = args.shift
|
||||
@@ -813,6 +815,7 @@ module ADN
|
||||
puts " Total archivos: #{archivos.length}"
|
||||
puts " Pendientes: #{pendientes.length}"
|
||||
puts " Ya procesados: #{archivos.length - pendientes.length}"
|
||||
puts " On-error: #{options[:on_error]}#{options[:on_error] == 'retry' ? " (max #{options[:retries]})" : ''}"
|
||||
puts ""
|
||||
|
||||
if pendientes.empty?
|
||||
@@ -823,36 +826,75 @@ module ADN
|
||||
adn_run = File.join(ADN::PROJECT_ROOT, 'adn', 'tools', 'run')
|
||||
timeout = options[:timeout] || 7200
|
||||
|
||||
# Tracking de resultados
|
||||
resultados = []
|
||||
abortado = false
|
||||
|
||||
pendientes.each_with_index do |arch, i|
|
||||
tamaño_gb = (arch[:tamaño].to_f / 1024**3).round(1)
|
||||
puts " #{Color::BOLD}[#{i+1}/#{pendientes.length}]#{Color::RESET} #{arch[:vm]} — #{arch[:archivo]} (#{tamaño_gb}GB)"
|
||||
|
||||
if options[:dry_run]
|
||||
puts " #{Color::YELLOW}[DRY-RUN] Lanzaría dron para: #{arch[:archivo]}#{Color::RESET}"
|
||||
resultados << { vm: arch[:vm], estado: :skipped }
|
||||
next
|
||||
end
|
||||
|
||||
# Lanzar dron atómico para este archivo
|
||||
# Lanzar dron atómico con reintentos
|
||||
nota = "Comprimir #{arch[:vm]} (#{tamaño_gb}GB)"
|
||||
cmd_dron = "#{adn_run} dron lanzar" \
|
||||
" --nota \"#{nota}\"" \
|
||||
" --timeout #{timeout}" \
|
||||
" -- #{adn_run} bkps run #{ref} --batch --archivo #{Shellwords.escape(arch[:archivo])}"
|
||||
|
||||
puts " 🛸 Lanzando dron..."
|
||||
resultado = system(cmd_dron)
|
||||
max_intentos = options[:on_error] == 'retry' ? options[:retries] + 1 : 1
|
||||
exito = false
|
||||
|
||||
if resultado
|
||||
max_intentos.times do |intento|
|
||||
etiqueta = max_intentos > 1 ? " (intento #{intento + 1}/#{max_intentos})" : ""
|
||||
puts " 🛸 Lanzando dron#{etiqueta}..."
|
||||
exito = system(cmd_dron)
|
||||
break if exito
|
||||
|
||||
if intento < max_intentos - 1
|
||||
puts " #{Color::YELLOW}⟳ Reintentando...#{Color::RESET}"
|
||||
end
|
||||
end
|
||||
|
||||
if exito
|
||||
puts " #{Color::GREEN}✔ Dron completado#{Color::RESET}"
|
||||
resultados << { vm: arch[:vm], estado: :ok }
|
||||
else
|
||||
puts " #{Color::RED}✖ Dron falló — deteniendo orquestación#{Color::RESET}"
|
||||
break
|
||||
resultados << { vm: arch[:vm], estado: :failed }
|
||||
case options[:on_error]
|
||||
when 'abort'
|
||||
puts " #{Color::RED}✖ Dron falló — deteniendo orquestación#{Color::RESET}"
|
||||
abortado = true
|
||||
break
|
||||
when 'continue'
|
||||
puts " #{Color::YELLOW}⚠ Dron falló — continuando con el siguiente#{Color::RESET}"
|
||||
when 'retry'
|
||||
puts " #{Color::RED}✖ Dron falló después de #{max_intentos} intentos — deteniendo#{Color::RESET}"
|
||||
abortado = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
puts ""
|
||||
end
|
||||
|
||||
puts "#{Color::BOLD}🐝 Orquestación finalizada.#{Color::RESET}"
|
||||
# Resumen final
|
||||
ok = resultados.count { |r| r[:estado] == :ok }
|
||||
failed = resultados.count { |r| r[:estado] == :failed }
|
||||
|
||||
puts "\n#{Color::BOLD}🐝 Resumen de Orquestación#{Color::RESET}"
|
||||
puts "═" * 40
|
||||
puts " ✅ Exitosos: #{ok}"
|
||||
puts " ❌ Fallidos: #{failed}" if failed > 0
|
||||
puts " ⏭️ Saltados: #{pendientes.length - ok - failed}" if abortado
|
||||
puts "#{Color::BOLD}🐝 Orquestación #{abortado ? 'abortada' : 'finalizada'}.#{Color::RESET}"
|
||||
|
||||
exit 1 if failed > 0
|
||||
end
|
||||
|
||||
def ejecutar_comando(comando, options = {})
|
||||
|
||||
Reference in New Issue
Block a user