163 lines
4.6 KiB
Bash
Executable File
163 lines
4.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Launch AAO in gateway mode (OpenAI-compatible LLM gateway, no UI).
|
|
#
|
|
# This is a sibling of scripts/server.sh (worker mode). Both can run
|
|
# concurrently on the same host because:
|
|
# - PID file: .gateway.pid (worker uses .server.pid)
|
|
# - Log file: logs/gateway.log (worker uses logs/server.log)
|
|
# - Listen port: $GATEWAY_PORT (default 4000)、worker は $PORT (default 9876)
|
|
# - DB: 同じ data/aao.db を SQLite WAL mode で共有
|
|
# (gateway は gateway_virtual_keys + gateway_key_usage の 2 table のみ touch)
|
|
#
|
|
# Usage:
|
|
# scripts/gateway.sh start
|
|
# scripts/gateway.sh stop
|
|
# scripts/gateway.sh restart
|
|
# scripts/gateway.sh status
|
|
# scripts/gateway.sh logs
|
|
#
|
|
# Env override:
|
|
# GATEWAY_PORT=4000 # gateway.listen_port を上書き (config.yaml より優先)
|
|
# AAO_CONFIG=/etc/aao/config-gateway.yaml # 専用 config を使う場合
|
|
# AAO_GATEWAY_NO_DB=1 # ステートレス起動 (virtual_keys は config 経由のみ、budget/rate-limit 無効)
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
|
PID_FILE="$PROJECT_DIR/.gateway.pid"
|
|
LOG_FILE="$PROJECT_DIR/logs/gateway.log"
|
|
GATEWAY_PORT="${GATEWAY_PORT:-4000}"
|
|
|
|
cd "$PROJECT_DIR"
|
|
|
|
usage() {
|
|
echo "Usage: $0 {start|stop|restart|status|logs}"
|
|
echo
|
|
echo "Env:"
|
|
echo " GATEWAY_PORT=$GATEWAY_PORT"
|
|
echo " AAO_CONFIG=${AAO_CONFIG:-<repo config.yaml>}"
|
|
echo " AAO_GATEWAY_NO_DB=${AAO_GATEWAY_NO_DB:-<unset, DB enabled>}"
|
|
exit 1
|
|
}
|
|
|
|
is_running() {
|
|
if [[ -f "$PID_FILE" ]]; then
|
|
local pid
|
|
pid=$(cat "$PID_FILE")
|
|
if kill -0 "$pid" 2>/dev/null; then
|
|
return 0
|
|
fi
|
|
rm -f "$PID_FILE"
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
do_start() {
|
|
if is_running; then
|
|
echo "Gateway already running (PID $(cat "$PID_FILE"))"
|
|
return 0
|
|
fi
|
|
|
|
mkdir -p "$(dirname "$LOG_FILE")"
|
|
|
|
echo "Checking runtime dependencies..."
|
|
"$SCRIPT_DIR/prepare.sh"
|
|
|
|
echo "Building..."
|
|
npm run build --silent 2>&1 | tail -1
|
|
|
|
echo "Starting gateway on port $GATEWAY_PORT..."
|
|
# AAO_MODE=gateway は src/main.ts の switch を gateway/bootstrap に向ける
|
|
# GATEWAY_PORT は src/gateway/config.ts が config.yaml の listen_port を
|
|
# env で上書きするためのキー (実装側で env > config の precedence)。
|
|
AAO_MODE=gateway \
|
|
GATEWAY_PORT="$GATEWAY_PORT" \
|
|
${AAO_CONFIG:+AAO_CONFIG="$AAO_CONFIG"} \
|
|
${AAO_GATEWAY_NO_DB:+AAO_GATEWAY_NO_DB="$AAO_GATEWAY_NO_DB"} \
|
|
nohup node dist/main.js >> "$LOG_FILE" 2>&1 &
|
|
local pid=$!
|
|
echo "$pid" > "$PID_FILE"
|
|
|
|
# Wait briefly and verify it started
|
|
sleep 2
|
|
if kill -0 "$pid" 2>/dev/null; then
|
|
echo "Gateway started (PID $pid, log: $LOG_FILE)"
|
|
echo " Health: curl http://localhost:$GATEWAY_PORT/health/liveness"
|
|
echo " Metrics: curl http://localhost:$GATEWAY_PORT/metrics"
|
|
else
|
|
rm -f "$PID_FILE"
|
|
echo "Gateway failed to start. Last 20 log lines:"
|
|
tail -20 "$LOG_FILE"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
do_stop() {
|
|
if ! is_running; then
|
|
echo "Gateway not running"
|
|
# Also kill any stray process on the port
|
|
local stray
|
|
stray=$(lsof -ti:"$GATEWAY_PORT" 2>/dev/null || true)
|
|
if [[ -n "$stray" ]]; then
|
|
echo "Found stray process on port $GATEWAY_PORT (PID $stray), killing..."
|
|
kill "$stray" 2>/dev/null || true
|
|
fi
|
|
return 0
|
|
fi
|
|
|
|
local pid
|
|
pid=$(cat "$PID_FILE")
|
|
echo "Stopping gateway (PID $pid)..."
|
|
# SIGTERM で graceful shutdown (gateway.shutdown_graceful_sec で SSE drain)
|
|
kill "$pid" 2>/dev/null || true
|
|
|
|
# Wait for graceful shutdown — gateway drain may take up to ~30s by default
|
|
for i in {1..60}; do
|
|
if ! kill -0 "$pid" 2>/dev/null; then
|
|
rm -f "$PID_FILE"
|
|
echo "Gateway stopped (graceful)"
|
|
return 0
|
|
fi
|
|
sleep 0.5
|
|
done
|
|
|
|
# Force kill
|
|
echo "Graceful shutdown timed out; force killing..."
|
|
kill -9 "$pid" 2>/dev/null || true
|
|
rm -f "$PID_FILE"
|
|
echo "Gateway stopped (forced)"
|
|
}
|
|
|
|
do_status() {
|
|
if is_running; then
|
|
local pid
|
|
pid=$(cat "$PID_FILE")
|
|
echo "Gateway running (PID $pid, port $GATEWAY_PORT)"
|
|
# Probe liveness for confirmation
|
|
if curl -sS -o /dev/null -w "%{http_code}" "http://localhost:$GATEWAY_PORT/health/liveness" 2>/dev/null | grep -q 200; then
|
|
echo " Liveness: OK"
|
|
else
|
|
echo " Liveness: NOT OK (process up but endpoint not responding)"
|
|
fi
|
|
else
|
|
echo "Gateway not running"
|
|
fi
|
|
}
|
|
|
|
do_logs() {
|
|
if [[ -f "$LOG_FILE" ]]; then
|
|
tail -f "$LOG_FILE"
|
|
else
|
|
echo "No log file found at $LOG_FILE"
|
|
fi
|
|
}
|
|
|
|
case "${1:-}" in
|
|
start) do_start ;;
|
|
stop) do_stop ;;
|
|
restart) do_stop; do_start ;;
|
|
status) do_status ;;
|
|
logs) do_logs ;;
|
|
*) usage ;;
|
|
esac
|