Spaces:
Paused
Paused
| # ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # scripts/start_demo.sh β one-shot demo for supervisor showcase | |
| # | |
| # What it does: | |
| # 1. Kills any previous demo processes (uvicorn / cloudflared) | |
| # 2. Starts FastAPI on 127.0.0.1:8181 (clean env, isolated from other venvs) | |
| # 3. Waits until /api/health returns 200 | |
| # 4. Starts a Cloudflare Quick Tunnel and prints the public URL | |
| # 5. On Ctrl-C, cleanly shuts down both processes | |
| # | |
| # Usage: | |
| # ./scripts/start_demo.sh | |
| # | |
| # Prereqs (already done by the agent on this machine): | |
| # - .venv/ Python 3.9 venv with all deps installed | |
| # - .local/bin/cloudflared (macOS arm64, downloaded from GitHub releases) | |
| # - models/rf_model.pkl (217 MB, real ERA5-trained Random Forest) | |
| # ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| set -euo pipefail | |
| PORT="${PORT:-8181}" | |
| ROOT="$(cd "$(dirname "$0")/.." && pwd)" | |
| LOG_DIR="${TMPDIR:-/tmp}" | |
| UVICORN_LOG="$LOG_DIR/mcx-uvicorn.log" | |
| TUNNEL_LOG="$LOG_DIR/mcx-tunnel.log" | |
| cd "$ROOT" | |
| # ββ 1. Kill leftovers from a previous run ββββββββββββββββββββββββββββββββ | |
| pkill -f "uvicorn backend.main:app.*--port $PORT" 2>/dev/null || true | |
| pkill -f "cloudflared tunnel --url http://127.0.0.1:$PORT" 2>/dev/null || true | |
| sleep 1 | |
| # ββ 2. Start FastAPI in the background βββββββββββββββββββββββββββββββββββ | |
| echo "βΆ Starting FastAPI on http://127.0.0.1:$PORT β¦" | |
| env -u PYTHONPATH -u VIRTUAL_ENV -u PYTHONHOME \ | |
| ".venv/bin/python" -m uvicorn backend.main:app \ | |
| --host 127.0.0.1 --port "$PORT" \ | |
| > "$UVICORN_LOG" 2>&1 & | |
| UVICORN_PID=$! | |
| cleanup() { | |
| echo | |
| echo "βΆ Shutting down (uvicorn=$UVICORN_PID, cloudflared=${CF_PID:-n/a})β¦" | |
| [[ -n "${CF_PID:-}" ]] && kill "$CF_PID" 2>/dev/null || true | |
| kill "$UVICORN_PID" 2>/dev/null || true | |
| wait 2>/dev/null || true | |
| echo "β Stopped. Logs preserved at:" | |
| echo " $UVICORN_LOG" | |
| echo " $TUNNEL_LOG" | |
| } | |
| trap cleanup EXIT INT TERM | |
| # ββ 3. Wait for /api/health ββββββββββββββββββββββββββββββββββββββββββββββ | |
| printf " waiting for ML model load " | |
| for _ in $(seq 1 40); do | |
| if curl -sf --max-time 1 --noproxy '*' "http://127.0.0.1:$PORT/api/health" >/dev/null 2>&1; then | |
| echo " β" | |
| break | |
| fi | |
| printf "." | |
| sleep 1 | |
| done | |
| if ! curl -sf --max-time 1 --noproxy '*' "http://127.0.0.1:$PORT/api/health" >/dev/null 2>&1; then | |
| echo | |
| echo "β FastAPI did not become ready in 40 s. Last log lines:" | |
| tail -20 "$UVICORN_LOG" | |
| exit 1 | |
| fi | |
| HEALTH=$(curl -s --noproxy '*' "http://127.0.0.1:$PORT/api/health") | |
| ML_LOADED=$(echo "$HEALTH" | python3 -c 'import json,sys; print(json.load(sys.stdin)["ml_loaded"])' 2>/dev/null || echo "?") | |
| echo " ML model loaded: $ML_LOADED (response: ${HEALTH:0:80}β¦)" | |
| echo | |
| # ββ 4. Start Cloudflare Quick Tunnel βββββββββββββββββββββββββββββββββββββ | |
| echo "βΆ Opening Cloudflare Quick Tunnel β¦" | |
| echo " (your public URL will print below as 'https://*.trycloudflare.com')" | |
| echo " βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ" | |
| # Run cloudflared in foreground so the user sees the URL and can Ctrl-C. | |
| ./.local/bin/cloudflared tunnel --url "http://127.0.0.1:$PORT" 2>&1 | tee "$TUNNEL_LOG" & | |
| CF_PID=$! | |
| wait "$CF_PID" | |