feat(brahman-demo): bootstrap script reproducible — broker + producer + consumer + 4 explorers
1#!/usr/bin/env bash
2# bootstrap-demo.sh — arranca un escenario reproducible de brahman:
3# broker standalone + 1 producer demo + 1 consumer demo (mismo flow
4# tipo, así el broker computa un Match y el broker-explorer lo ve en
5# sesiones + timeline) + abre los 4 explorers GPUI.
6#
7# Uso:
8# scripts/bootstrap-demo.sh # default: abre todos
9# scripts/bootstrap-demo.sh broker # sólo broker + producers
10# scripts/bootstrap-demo.sh broker only # ni siquiera producers
11#
12# Limpieza: Ctrl-C dispara `cleanup` que mata todos los procesos
13# spawneados por este script (broker, producers, explorers). Logs
14# de cada uno quedan bajo $LOG_DIR (default /tmp/brahman-demo) para
15# que después se puedan revisar — el script los borra cuando se
16# vuelve a invocar (no acumula).
17#
18# Asume `cargo build --workspace` ya hecho. Si no, descomentá la
19# línea `cargo build` debajo (toma minutos en cold cache).
20
21set -euo pipefail
22
23LOG_DIR="${BRAHMAN_DEMO_LOG_DIR:-/tmp/brahman-demo}"
24SOCKET="${BRAHMAN_INIT_SOCKET:-/tmp/brahman-init.sock}"
25MODE="${1:-all}"
26
27# Path resolution: si el script vive en repo/scripts/, el repo es el padre.
28SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
29REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
30cd "$REPO_DIR"
31
32# Limpieza de logs viejos. Mantenemos el dir, sólo vaciamos.
33mkdir -p "$LOG_DIR"
34rm -f "$LOG_DIR"/*.log
35
36# Track de PIDs spawneados para que el trap los mate todos.
37PIDS=()
38
39cleanup() {
40 echo
41 echo "[bootstrap-demo] cleanup — matando ${#PIDS[@]} procesos"
42 for pid in "${PIDS[@]}"; do
43 if kill -0 "$pid" 2>/dev/null; then
44 kill "$pid" 2>/dev/null || true
45 fi
46 done
47 # Espera breve para que cierren cleanly antes de SIGKILL.
48 sleep 1
49 for pid in "${PIDS[@]}"; do
50 if kill -0 "$pid" 2>/dev/null; then
51 kill -9 "$pid" 2>/dev/null || true
52 fi
53 done
54 # El socket lo limpia el broker al hacer Drop, pero defendemos
55 # contra crashes.
56 rm -f "$SOCKET"
57 echo "[bootstrap-demo] terminado. logs: $LOG_DIR"
58}
59trap cleanup EXIT INT TERM
60
61# Si querés re-build automático, descomentá:
62# echo "[bootstrap-demo] cargo build (puede tomar minutos en cold cache)"
63# cargo build -p brahman-demo -p brahman-broker-explorer \
64# -p nakui-explorer -p nouser-explorer -p minga-explorer
65
66# 1. Broker. Bind del socket. Si ya hay un proceso ocupando el
67# socket, esto falla rápido — el cleanup del trap se encarga.
68echo "[bootstrap-demo] arrancando broker → $SOCKET"
69BRAHMAN_INIT_SOCKET="$SOCKET" \
70 cargo run --quiet -p brahman-demo --bin brahman-demo-broker \
71 > "$LOG_DIR/broker.log" 2>&1 &
72PIDS+=($!)
73
74# Esperar a que el socket aparezca (el broker hace bind tras boot).
75# Sin esto, los siguientes connects rebotan ENOENT.
76for _ in $(seq 1 50); do
77 [ -S "$SOCKET" ] && break
78 sleep 0.1
79done
80if [ ! -S "$SOCKET" ]; then
81 echo "[bootstrap-demo] ERROR: broker no creó el socket en 5s — ver $LOG_DIR/broker.log"
82 exit 1
83fi
84echo "[bootstrap-demo] broker UP (pid ${PIDS[-1]})"
85
86# 2. Producer + consumer (a menos que MODE=only).
87if [ "$MODE" != "only" ]; then
88 echo "[bootstrap-demo] arrancando producer (flow demo-stream/json)"
89 BRAHMAN_INIT_SOCKET="$SOCKET" \
90 BRAHMAN_DEMO_LABEL=demo-producer \
91 BRAHMAN_DEMO_FLOW=demo-stream \
92 BRAHMAN_DEMO_TYPE=json \
93 cargo run --quiet -p brahman-demo --bin brahman-demo-producer \
94 > "$LOG_DIR/producer.log" 2>&1 &
95 PIDS+=($!)
96
97 echo "[bootstrap-demo] arrancando consumer (flow demo-feed/json — matchea con producer)"
98 BRAHMAN_INIT_SOCKET="$SOCKET" \
99 BRAHMAN_DEMO_LABEL=demo-consumer \
100 BRAHMAN_DEMO_FLOW=demo-feed \
101 BRAHMAN_DEMO_TYPE=json \
102 cargo run --quiet -p brahman-demo --bin brahman-demo-consumer \
103 > "$LOG_DIR/consumer.log" 2>&1 &
104 PIDS+=($!)
105
106 # Pequeño grace para que los handshakes completen antes que los
107 # explorers se conecten (sino el primer ListSessions devuelve algo
108 # transitorio sin las sesiones demo).
109 sleep 1
110fi
111
112# 3. Explorers GPUI (a menos que MODE=broker).
113if [ "$MODE" != "broker" ] && [ "$MODE" != "only" ]; then
114 echo "[bootstrap-demo] abriendo brahman-broker-explorer"
115 BRAHMAN_INIT_SOCKET="$SOCKET" \
116 cargo run --quiet -p brahman-broker-explorer \
117 > "$LOG_DIR/broker-explorer.log" 2>&1 &
118 PIDS+=($!)
119
120 echo "[bootstrap-demo] abriendo nouser-explorer (descubrirá vía broker si nouserd corre)"
121 BRAHMAN_INIT_SOCKET="$SOCKET" \
122 cargo run --quiet -p nouser-explorer \
123 > "$LOG_DIR/nouser-explorer.log" 2>&1 &
124 PIDS+=($!)
125
126 # nakui-explorer y minga-explorer son standalone (no usan broker)
127 # — los abrimos igual para tener el dashboard completo. Apuntan a
128 # paths default; si no hay nakui-events.jsonl o repo minga, sólo
129 # mostrarán el banner "esperando…".
130 echo "[bootstrap-demo] abriendo nakui-explorer (standalone)"
131 cargo run --quiet -p nakui-explorer > "$LOG_DIR/nakui-explorer.log" 2>&1 &
132 PIDS+=($!)
133
134 echo "[bootstrap-demo] abriendo minga-explorer (standalone)"
135 cargo run --quiet -p minga-explorer > "$LOG_DIR/minga-explorer.log" 2>&1 &
136 PIDS+=($!)
137fi
138
139echo
140echo "[bootstrap-demo] todo arriba — Ctrl-C para parar todo"
141echo "[bootstrap-demo] logs en $LOG_DIR/"
142echo
143
144# Wait sobre el broker: si éste cae, todo el demo deja de tener
145# sentido. El trap se encarga del resto.
146wait "${PIDS[0]}"