#!/usr/bin/env bash # bootstrap-demo.sh — arranca un escenario reproducible de brahman: # broker standalone + 1 producer demo + 1 consumer demo (mismo flow # tipo, así el broker computa un Match y el broker-explorer lo ve en # sesiones + timeline) + abre los 4 explorers GPUI. # # Uso: # scripts/bootstrap-demo.sh # default: abre todos # scripts/bootstrap-demo.sh broker # sólo broker + producers # scripts/bootstrap-demo.sh broker only # ni siquiera producers # # Limpieza: Ctrl-C dispara `cleanup` que mata todos los procesos # spawneados por este script (broker, producers, explorers). Logs # de cada uno quedan bajo $LOG_DIR (default /tmp/brahman-demo) para # que después se puedan revisar — el script los borra cuando se # vuelve a invocar (no acumula). # # Asume `cargo build --workspace` ya hecho. Si no, descomentá la # línea `cargo build` debajo (toma minutos en cold cache). set -euo pipefail LOG_DIR="${BRAHMAN_DEMO_LOG_DIR:-/tmp/brahman-demo}" SOCKET="${BRAHMAN_INIT_SOCKET:-/tmp/brahman-init.sock}" MODE="${1:-all}" # Path resolution: si el script vive en repo/scripts/, el repo es el padre. SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" cd "$REPO_DIR" # Limpieza de logs viejos. Mantenemos el dir, sólo vaciamos. mkdir -p "$LOG_DIR" rm -f "$LOG_DIR"/*.log # Track de PIDs spawneados para que el trap los mate todos. PIDS=() cleanup() { echo echo "[bootstrap-demo] cleanup — matando ${#PIDS[@]} procesos" for pid in "${PIDS[@]}"; do if kill -0 "$pid" 2>/dev/null; then kill "$pid" 2>/dev/null || true fi done # Espera breve para que cierren cleanly antes de SIGKILL. sleep 1 for pid in "${PIDS[@]}"; do if kill -0 "$pid" 2>/dev/null; then kill -9 "$pid" 2>/dev/null || true fi done # El socket lo limpia el broker al hacer Drop, pero defendemos # contra crashes. rm -f "$SOCKET" echo "[bootstrap-demo] terminado. logs: $LOG_DIR" } trap cleanup EXIT INT TERM # Si querés re-build automático, descomentá: # echo "[bootstrap-demo] cargo build (puede tomar minutos en cold cache)" # cargo build -p brahman-demo -p brahman-broker-explorer \ # -p nakui-explorer -p nouser-explorer -p minga-explorer # 1. Broker. Bind del socket. Si ya hay un proceso ocupando el # socket, esto falla rápido — el cleanup del trap se encarga. echo "[bootstrap-demo] arrancando broker → $SOCKET" BRAHMAN_INIT_SOCKET="$SOCKET" \ cargo run --quiet -p brahman-demo --bin brahman-demo-broker \ > "$LOG_DIR/broker.log" 2>&1 & PIDS+=($!) # Esperar a que el socket aparezca (el broker hace bind tras boot). # Sin esto, los siguientes connects rebotan ENOENT. for _ in $(seq 1 50); do [ -S "$SOCKET" ] && break sleep 0.1 done if [ ! -S "$SOCKET" ]; then echo "[bootstrap-demo] ERROR: broker no creó el socket en 5s — ver $LOG_DIR/broker.log" exit 1 fi echo "[bootstrap-demo] broker UP (pid ${PIDS[-1]})" # 2. Producer + consumer (a menos que MODE=only). if [ "$MODE" != "only" ]; then echo "[bootstrap-demo] arrancando producer (flow demo-stream/json)" BRAHMAN_INIT_SOCKET="$SOCKET" \ BRAHMAN_DEMO_LABEL=demo-producer \ BRAHMAN_DEMO_FLOW=demo-stream \ BRAHMAN_DEMO_TYPE=json \ cargo run --quiet -p brahman-demo --bin brahman-demo-producer \ > "$LOG_DIR/producer.log" 2>&1 & PIDS+=($!) echo "[bootstrap-demo] arrancando consumer (flow demo-feed/json — matchea con producer)" BRAHMAN_INIT_SOCKET="$SOCKET" \ BRAHMAN_DEMO_LABEL=demo-consumer \ BRAHMAN_DEMO_FLOW=demo-feed \ BRAHMAN_DEMO_TYPE=json \ cargo run --quiet -p brahman-demo --bin brahman-demo-consumer \ > "$LOG_DIR/consumer.log" 2>&1 & PIDS+=($!) # Pequeño grace para que los handshakes completen antes que los # explorers se conecten (sino el primer ListSessions devuelve algo # transitorio sin las sesiones demo). sleep 1 fi # 3. Explorers GPUI (a menos que MODE=broker). if [ "$MODE" != "broker" ] && [ "$MODE" != "only" ]; then echo "[bootstrap-demo] abriendo brahman-broker-explorer" BRAHMAN_INIT_SOCKET="$SOCKET" \ cargo run --quiet -p brahman-broker-explorer \ > "$LOG_DIR/broker-explorer.log" 2>&1 & PIDS+=($!) echo "[bootstrap-demo] abriendo nouser-explorer (descubrirá vía broker si nouserd corre)" BRAHMAN_INIT_SOCKET="$SOCKET" \ cargo run --quiet -p nouser-explorer \ > "$LOG_DIR/nouser-explorer.log" 2>&1 & PIDS+=($!) # nakui-explorer y minga-explorer son standalone (no usan broker) # — los abrimos igual para tener el dashboard completo. Apuntan a # paths default; si no hay nakui-events.jsonl o repo minga, sólo # mostrarán el banner "esperando…". echo "[bootstrap-demo] abriendo nakui-explorer (standalone)" cargo run --quiet -p nakui-explorer > "$LOG_DIR/nakui-explorer.log" 2>&1 & PIDS+=($!) echo "[bootstrap-demo] abriendo minga-explorer (standalone)" cargo run --quiet -p minga-explorer > "$LOG_DIR/minga-explorer.log" 2>&1 & PIDS+=($!) fi echo echo "[bootstrap-demo] todo arriba — Ctrl-C para parar todo" echo "[bootstrap-demo] logs en $LOG_DIR/" echo # Wait sobre el broker: si éste cae, todo el demo deja de tener # sentido. El trap se encarga del resto. wait "${PIDS[0]}"