Principio "Menos es Más": código común centralizado en un solo lugar. Cambios: - Nuevo módulo Dron::Base con funcionalidad compartida: - logger: Logger compartido (evita crear múltiples instancias) - db_query: Ejecución de SQL con resultados - db_exec: Ejecución de SQL sin resultados - formato_duracion: Utilitario para formatear segundos - slice_safe: Slice seguro de strings - blank?: Verificación de strings vacíos/nulos - Todos los módulos atómicos (ejecutor, vigilante, sanador, bitacora) ahora usan Base.logger, Base.db_query, Base.db_exec Beneficios: - Un solo lugar para corregir errores comunes - Menos duplicación de código (~40% menos líneas) - Consistencia en manejo de logs y DB - Fácil extensión: nuevos drones heredan funcionalidad automática Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
76 lines
3.0 KiB
Ruby
76 lines
3.0 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# Dron::Bitacora — Módulo atómico para registro en bitácora humana
|
|
#
|
|
# Responsabilidad única: Gestionar registro de eventos en bitácora
|
|
|
|
require_relative 'base'
|
|
|
|
module Dron
|
|
class Bitacora
|
|
class << self
|
|
def iniciar(nota:, nodo_id: 1, modo: 'A')
|
|
descripcion = "🛸 dron: #{nota}"
|
|
Base.logger.info("📝 Bitácora: Iniciando evento - #{nota}")
|
|
sql = "INSERT INTO bitacoras.events (nodo_id, descripcion, estado, modo, inicio) VALUES ($1, $2, $3, $4, $5) RETURNING id"
|
|
resultado = Base.db_exec(sql, [nodo_id, descripcion, '⏳', modo, Time.now.strftime('%H:%M')])
|
|
evento_id = resultado.first['id']
|
|
Base.logger.info("📝 Evento creado: ##{evento_id}")
|
|
evento_id
|
|
rescue StandardError => e
|
|
Base.logger.error("📝 Error creando evento: #{e.message}")
|
|
nil
|
|
end
|
|
|
|
def finalizar(evento_id, exit_code:, nota: nil)
|
|
evento = Base.db_query("SELECT * FROM bitacoras.events WHERE id = $1", [evento_id]).first
|
|
return false unless evento
|
|
|
|
estado_icono = exit_code == 0 ? '✅' : '❌'
|
|
nota_original = evento['descripcion'].to_s.gsub('🛸 dron: ', '').split(' — ').first
|
|
descripcion = "🛸 dron: #{nota_original} — #{estado_icono}#{nota ? " — #{nota}" : ''}"
|
|
|
|
Base.logger.info("📝 Bitácora: Finalizando evento ##{evento_id} - #{estado_icono}")
|
|
sql = "UPDATE bitacoras.events SET descripcion = $1, estado = $2, fin = $3, updated_at = NOW() WHERE id = $4"
|
|
Base.db_exec(sql, [descripcion, estado_icono, Time.now.strftime('%H:%M'), evento_id])
|
|
true
|
|
rescue StandardError => e
|
|
Base.logger.error("📝 Error actualizando evento: #{e.message}")
|
|
false
|
|
end
|
|
|
|
def auto(nota:, &bloque)
|
|
evento_id = iniciar(nota: nota)
|
|
inicio = Time.now
|
|
resultado = nil
|
|
exit_code = 0
|
|
|
|
begin
|
|
resultado = yield
|
|
rescue StandardError => e
|
|
Base.logger.error("📝 Error en ejecución AUTO: #{e.message}")
|
|
exit_code = 1
|
|
end
|
|
|
|
duracion = (Time.now - inicio).round(2)
|
|
finalizar(evento_id, exit_code: exit_code, nota: "#{duracion}s") if evento_id
|
|
{ evento_id: evento_id, exit_code: exit_code, resultado: resultado, duracion: duracion }
|
|
end
|
|
|
|
def vincular_flujo(evento_id, flujo_id)
|
|
evento = Base.db_query("SELECT * FROM bitacoras.events WHERE id = $1", [evento_id]).first
|
|
return false unless evento
|
|
|
|
metadata_hash = (evento['metadata'] && JSON.parse(evento['metadata'])) rescue {}
|
|
metadata_hash['flujo_id'] = flujo_id
|
|
Base.db_exec("UPDATE bitacoras.events SET metadata = $1 WHERE id = $2", [metadata_hash.to_json, evento_id])
|
|
Base.logger.info("📝 Evento ##{evento_id} vinculado al flujo #{flujo_id}")
|
|
true
|
|
rescue StandardError => e
|
|
Base.logger.error("📝 Error vinculando flujo: #{e.message}")
|
|
false
|
|
end
|
|
end
|
|
end
|
|
end
|