Files
fn_registry/bash/functions/infra/supervise_fleetview_tui.sh
T
egutierrez 46954d8584 feat(infra): auto-commit con 8 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-24 15:35:59 +02:00

130 lines
5.3 KiB
Bash

#!/usr/bin/env bash
# supervise_fleetview_tui — bucle supervisor que mantiene viva la TUI fleetview.
#
# Lanza el binario fleetview y, si sale (crash, panic, kill de su proceso o de su
# pane), lo relanza tras un pequeno backoff. Asi el panel de control de la flota
# NUNCA se pierde por un fallo puntual: es la pieza que hace resiliente al pane
# izquierdo de la sesion tmux FleetView (lo invoca launch_fleetclaude).
#
# Dos valvulas de escape para no hacer respawn infinito:
# - Sentinel file: si tras una salida existe el fichero centinela, se borra y
# el bucle termina (parada voluntaria solicitada por el usuario). El default
# es $HOME/.claude/fleet/tui_stop_<socket>; pararla a mano: `touch <sentinel>`
# y dejar que la TUI salga (o matar su proceso).
# - Crash-loop guard: si la TUI sale demasiado rapido (uptime < min_uptime
# segundos) muchas veces seguidas (>= max_fast_exits), el supervisor se rinde
# y devuelve != 0, para no quemar CPU relanzando un binario roto en caliente.
# Un arranque que dura >= min_uptime resetea el contador.
#
# Funcion IMPURA: lanza un proceso en bucle y lee/escribe un fichero centinela.
#
# Overrides de entorno (testabilidad, no para uso normal):
# FLEET_SOCKET socket del perfil; fija el nombre del sentinel por defecto.
set -euo pipefail
IFS=$' \t\n'
supervise_fleetview_tui() {
local bin="" socket="" sentinel="" backoff=1 min_uptime=2 max_fast_exits=5
while [[ $# -gt 0 ]]; do
case "$1" in
--bin) shift; bin="${1:-}" ;;
--socket) shift; socket="${1:-}" ;;
--sentinel) shift; sentinel="${1:-}" ;;
--backoff) shift; backoff="${1:-1}" ;;
--min-uptime) shift; min_uptime="${1:-2}" ;;
--max-fast-exits) shift; max_fast_exits="${1:-5}" ;;
-h|--help)
cat <<'USAGE'
Uso: supervise_fleetview_tui --bin <path> [opciones]
Bucle supervisor: corre el binario fleetview y lo relanza si sale, para que el
panel de la flota nunca se pierda por un crash/kill puntual.
Opciones:
--bin <path> Ruta al binario fleetview (obligatorio).
--socket <s> Socket del perfil FleetView. Default: $FLEET_SOCKET o "fleet".
--sentinel <path> Fichero centinela de parada voluntaria.
Default: $HOME/.claude/fleet/tui_stop_<socket>.
--backoff <s> Segundos de espera antes de relanzar. Default: 1.
--min-uptime <s> Umbral (s) para considerar una salida "rapida". Default: 2.
--max-fast-exits <n> Salidas rapidas seguidas tras las que el supervisor se
rinde (crash-loop guard). Default: 5.
-h, --help Esta ayuda.
Parar el bucle a mano: `touch <sentinel>` y dejar que la TUI salga (o matar su
proceso); en el siguiente ciclo el supervisor ve el sentinel, lo borra y termina.
Salida: 0 parada voluntaria (sentinel); 1 binario no ejecutable / uso incorrecto;
3 el supervisor se rindio por crash-loop (demasiadas salidas rapidas seguidas).
USAGE
return 0 ;;
--*)
echo "supervise_fleetview_tui: opcion desconocida '$1' (usa -h)" >&2
return 1 ;;
*)
if [[ -z "$bin" ]]; then
bin="$1"
else
echo "supervise_fleetview_tui: argumento extra '$1' (bin ya es '$bin')" >&2
return 1
fi ;;
esac
shift
done
[[ -z "$bin" ]] && {
echo "supervise_fleetview_tui: falta --bin <path> al binario fleetview. Usa -h." >&2
return 1
}
[[ -z "$socket" ]] && socket="${FLEET_SOCKET:-fleet}"
[[ -z "$sentinel" ]] && sentinel="$HOME/.claude/fleet/tui_stop_${socket}"
mkdir -p "$(dirname "$sentinel")" 2>/dev/null || true
if [[ ! -x "$bin" ]]; then
echo "supervise_fleetview_tui: binario '$bin' no es ejecutable. Compila la TUI: cd apps/fleetview && go build -o fleetview ." >&2
return 1
fi
# Limpiar un sentinel huerfano de una sesion anterior, para no parar al arrancar.
[[ -f "$sentinel" ]] && rm -f "$sentinel" 2>/dev/null || true
local fast_exits=0
while true; do
local start end uptime code
start=$(date +%s)
set +e
"$bin"
code=$?
set -e
end=$(date +%s)
uptime=$(( end - start ))
# Valvula 1 — parada voluntaria por sentinel.
if [[ -f "$sentinel" ]]; then
rm -f "$sentinel" 2>/dev/null || true
echo "[fleetview: parada solicitada via sentinel ($sentinel) — fin del supervisor]"
return 0
fi
# Valvula 2 — crash-loop guard.
if [[ "$uptime" -lt "$min_uptime" ]]; then
fast_exits=$(( fast_exits + 1 ))
else
fast_exits=0
fi
if [[ "$fast_exits" -ge "$max_fast_exits" ]]; then
echo "[fleetview: $fast_exits salidas rapidas seguidas (ultimo code=$code) — el supervisor se rinde para no hacer respawn infinito. Inspecciona el binario y relanza.]" >&2
return 3
fi
echo "[fleetview salio (code=$code, uptime=${uptime}s) — relanzando en ${backoff}s. Para parar: touch $sentinel, o Ctrl-C.]"
sleep "$backoff"
done
}
# Permitir ejecutar el archivo directamente (no solo como funcion sourced).
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
supervise_fleetview_tui "$@"
fi