Spaces:
Paused
Paused
File size: 3,940 Bytes
4eefabb | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | #!/usr/bin/env bash
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# 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"
|