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"