fix(dron): Ejecutor funcional + tabla events
Cambios: - ejecutor.rb: Corregir lectura de output con Open3 - bitacora_db.rb: Agregar métodos crear_evento/actualizar_evento (public) - dron_db.rb: Corregir conversión de PG::Result a Hash (.first.to_h) - vigilante.rb: Corregir formato de fecha en dashboard - migrations/004: Crear tabla bitacoras.events para Bitácora Web Pruebas: - dron lanzar --evento AUTO --nota "Test" -- echo "hola" ✅ - dron flota ✅ - dron salud ✅ Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
3d2a988951
commit
be3a78c50a
@@ -984,38 +984,77 @@ module BitacorasDB
|
||||
end
|
||||
end
|
||||
|
||||
# Convierte un resultado PG a Hash
|
||||
def result_to_hash(result)
|
||||
return {} if result.ntuples.zero?
|
||||
result.first.to_h
|
||||
end
|
||||
# Convierte un resultado PG a Hash
|
||||
def result_to_hash(result)
|
||||
return {} if result.ntuples.zero?
|
||||
result.first.to_h
|
||||
end
|
||||
|
||||
# Ejecuta hooks personalizados después de operaciones de entrada
|
||||
# Esto implementa el concepto de DB Hooks para migrar triggers.yml a capa de datos
|
||||
#
|
||||
# @param entrada [Hash] La entrada que fue creada o actualizada
|
||||
# @param accion [Symbol] :crear o :actualizar
|
||||
def ejecutar_hooks_entrada(entrada, accion)
|
||||
# Hook para proyectos con etiqueta [P2604]
|
||||
if entrada[:descripcion]&.match?(/\[P2604\]/)
|
||||
proyecto_codigo = entrada[:descripcion].match(/\[P2604\.(\d+)\.(\d+)\.(\d+)\]/)&.to_s
|
||||
if proyecto_codigo
|
||||
# Normalizar formato: P2604.05.01 -> P2604
|
||||
proyecto_base = proyecto_codigo.split('.')[0..1].join('.')
|
||||
|
||||
# Actualizar el manifiesto del proyecto en la base de datos
|
||||
proyecto = find_proyecto_by_codigo(proyecto_base)
|
||||
if proyecto
|
||||
# Aquí podríamos actualizar algún campo del proyecto basado en la entrada
|
||||
# Por ahora, solo registramos que se debería actualizar
|
||||
@logger&.info("Hook ejecutado: Entrada #{accion} para proyecto #{proyecto_base} detectada")
|
||||
# En una implementación completa, aquí actualizaríamos el manifiesto del proyecto
|
||||
end
|
||||
# Ejecuta hooks personalizados después de operaciones de entrada
|
||||
def ejecutar_hooks_entrada(entrada, accion)
|
||||
if entrada[:descripcion]&.match?(/\[P2604\]/)
|
||||
proyecto_codigo = entrada[:descripcion].match(/\[P2604\.(\d+)\.(\d+)\.(\d+)\]/)&.to_s
|
||||
if proyecto_codigo
|
||||
proyecto_base = proyecto_codigo.split('.')[0..1].join('.')
|
||||
proyecto = find_proyecto_by_codigo(proyecto_base)
|
||||
if proyecto
|
||||
@logger&.info("Hook ejecutado: Entrada #{accion} para proyecto #{proyecto_base} detectada")
|
||||
end
|
||||
end
|
||||
|
||||
# Otros hooks podrían ir aquí...
|
||||
# Por ejemplo, hooks para sincronización con nodos, etc.
|
||||
end
|
||||
end
|
||||
|
||||
public
|
||||
|
||||
# Crear un evento en la tabla events (visible en Bitácora Web)
|
||||
def crear_evento(nodo_id:, descripcion:, estado: '⏳', inicio: nil, fin: nil, modo: 'A', metadata: nil)
|
||||
inicio ||= Time.now.strftime('%H:%M')
|
||||
query = <<~SQL
|
||||
INSERT INTO bitacoras.events (nodo_id, descripcion, estado, inicio, fin, modo, metadata)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||
RETURNING id
|
||||
SQL
|
||||
result = @connection.exec_params(query, [nodo_id, descripcion, estado, inicio, fin, modo, metadata&.to_json])
|
||||
result.first.to_h
|
||||
end
|
||||
|
||||
# Actualizar un evento existente
|
||||
def actualizar_evento(id, descripcion: nil, estado: nil, fin: nil)
|
||||
set_clauses = []
|
||||
values = []
|
||||
i = 1
|
||||
|
||||
if descripcion
|
||||
set_clauses << "descripcion = $#{i}"
|
||||
values << descripcion
|
||||
i += 1
|
||||
end
|
||||
|
||||
if estado
|
||||
set_clauses << "estado = $#{i}"
|
||||
values << estado
|
||||
i += 1
|
||||
end
|
||||
|
||||
if fin
|
||||
set_clauses << "fin = $#{i}"
|
||||
values << fin
|
||||
i += 1
|
||||
end
|
||||
|
||||
return nil if set_clauses.empty?
|
||||
|
||||
set_clauses << "updated_at = NOW()"
|
||||
query = <<~SQL
|
||||
UPDATE bitacoras.events
|
||||
SET #{set_clauses.join(', ')}
|
||||
WHERE id = $#{i}
|
||||
RETURNING *
|
||||
SQL
|
||||
|
||||
values << id
|
||||
result = @connection.exec_params(query, values)
|
||||
result.first.to_h
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -56,7 +56,7 @@ module ADN
|
||||
dron_id = generar_dron_id
|
||||
params = [dron_id, tipo, ESTADOS[:running], cmd, flujo_id, metadata.to_json]
|
||||
|
||||
resultado = BitacorasDB::BitacoraDB.with_connection { |db| db.execute(sql, params) }
|
||||
resultado = BitacorasDB::BitacoraDB.with_connection { |db| db.execute(sql, params) }.first.to_h
|
||||
|
||||
# Actualizar heartbeat inicial
|
||||
actualizar_heartbeat(dron_id)
|
||||
@@ -88,7 +88,7 @@ module ADN
|
||||
RETURNING *
|
||||
SQL
|
||||
|
||||
resultado = BitacorasDB::BitacoraDB.with_connection { |db| db.execute(sql, [estado, exit_code, output, dron_id]) }
|
||||
resultado = BitacorasDB::BitacoraDB.with_connection { |db| db.execute(sql, [estado, exit_code, output, dron_id]) }.first.to_h
|
||||
|
||||
# Actualizar métricas diarias
|
||||
actualizar_metricas(dron_id, estado)
|
||||
@@ -118,7 +118,7 @@ module ADN
|
||||
# @return [Hash, nil] Datos del dron o nil si no existe
|
||||
def obtener_dron(dron_id)
|
||||
sql = 'SELECT * FROM bitacoras.dron_logs WHERE dron_id = $1'
|
||||
resultado = BitacorasDB::BitacoraDB.with_connection { |db| db.execute(sql, [dron_id]) }
|
||||
resultado = BitacorasDB::BitacoraDB.with_connection { |db| db.execute(sql, [dron_id]) }.first.to_h
|
||||
resultado.first
|
||||
end
|
||||
|
||||
@@ -176,7 +176,7 @@ module ADN
|
||||
RETURNING reintentos
|
||||
SQL
|
||||
|
||||
resultado = BitacorasDB::BitacoraDB.with_connection { |db| db.execute(sql, [dron_id]) }
|
||||
resultado = BitacorasDB::BitacoraDB.with_connection { |db| db.execute(sql, [dron_id]) }.first.to_h
|
||||
resultado.first['reintentos'].to_i
|
||||
end
|
||||
|
||||
@@ -229,7 +229,7 @@ module ADN
|
||||
# @return [Hash, nil] Métricas o nil si no existen
|
||||
def obtener_metricas(fecha:, tipo:)
|
||||
sql = 'SELECT * FROM bitacoras.dron_metricas WHERE fecha = $1 AND dron_tipo = $2'
|
||||
resultado = BitacorasDB::BitacoraDB.with_connection { |db| db.execute(sql, [fecha, tipo]) }
|
||||
resultado = BitacorasDB::BitacoraDB.with_connection { |db| db.execute(sql, [fecha, tipo]) }.first.to_h
|
||||
resultado.first
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user