strat-gameplay-webapp/stop-services.sh
Cal Corum b68e3ceacf CLAUDE: Improve service scripts and fix WebSocket plugin conflict
Service Scripts:
- start-services.sh: Add pre-flight checks, health monitoring, --dev/--prod modes,
  port options, dependency checks, and version logging
- stop-services.sh: Add port 3000 cleanup, verification, --quiet/--force flags
- status-services.sh: New script for monitoring service status with --watch mode

WebSocket:
- Remove conflicting socket.client.ts plugin that was interfering with
  useWebSocket.ts composable (used JWT auth vs cookie auth)
- Add debugging logs to useWebSocket.ts to diagnose intermittent connection issues

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 15:23:41 -06:00

278 lines
7.7 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# Stop both backend and frontend services
# Enhanced to kill entire process trees, clean up orphans, and verify shutdown
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LOG_DIR="$SCRIPT_DIR/logs"
BACKEND_PORT=8000
FRONTEND_PORT=3000
# Parse arguments
QUIET_MODE=false
FORCE_MODE=false
while [[ $# -gt 0 ]]; do
case $1 in
--quiet|-q)
QUIET_MODE=true
shift
;;
--force|-f)
FORCE_MODE=true
shift
;;
--help|-h)
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Options:"
echo " --quiet, -q Minimal output"
echo " --force, -f Skip graceful shutdown, kill immediately"
echo " --help, -h Show this help message"
exit 0
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done
log() {
if [ "$QUIET_MODE" = false ]; then
echo "$@"
fi
}
log "========================================"
log "🛑 Stopping SBA Gameplay Services"
log "========================================"
log ""
# Function to kill process tree
kill_tree() {
local pid=$1
local sig=${2:-TERM}
# Get all child PIDs
local children=$(pgrep -P "$pid" 2>/dev/null || true)
# Kill children first (depth-first)
for child in $children; do
kill_tree "$child" "$sig"
done
# Kill the parent
if ps -p "$pid" > /dev/null 2>&1; then
kill -"$sig" "$pid" 2>/dev/null || true
fi
}
# Function to stop a service gracefully
stop_service() {
local name=$1
local pid_file=$2
local icon=$3
if [ -f "$pid_file" ]; then
local pid=$(cat "$pid_file")
if ps -p "$pid" > /dev/null 2>&1; then
log "$icon Stopping $name (PID: $pid)..."
if [ "$FORCE_MODE" = true ]; then
# Force mode: kill immediately
kill_tree "$pid" KILL
log "$name killed (force mode)"
else
# Graceful mode: SIGTERM first, then SIGKILL
kill_tree "$pid" TERM
# Wait up to 5 seconds for graceful shutdown
local wait_count=0
while [ $wait_count -lt 5 ]; do
if ! ps -p "$pid" > /dev/null 2>&1; then
break
fi
sleep 1
wait_count=$((wait_count + 1))
done
# Force kill if still running
if ps -p "$pid" > /dev/null 2>&1; then
log " → Graceful shutdown timed out, forcing..."
kill_tree "$pid" KILL
sleep 1
fi
if ps -p "$pid" > /dev/null 2>&1; then
log " ⚠️ $name may still be running"
else
log "$name stopped"
fi
fi
else
log " ⚠️ $name process not found (stale PID file)"
fi
rm -f "$pid_file"
else
log " No $name PID file found"
fi
}
# Stop Backend
stop_service "Backend" "$LOG_DIR/backend.pid" "📡"
log ""
# Stop Frontend
stop_service "Frontend" "$LOG_DIR/frontend.pid" "🎨"
log ""
# ============================================
# AGGRESSIVE CLEANUP: Kill orphaned processes
# ============================================
log "🔍 Checking for orphaned processes..."
ORPHANS_FOUND=false
# Kill all backend processes for this specific app
# Use more specific pattern to avoid killing unrelated processes
BACKEND_PATTERN="python.*app\.main"
BACKEND_PIDS=$(pgrep -f "$BACKEND_PATTERN" 2>/dev/null || true)
# Also check for uvicorn processes
UVICORN_PATTERN="uvicorn.*app\.main"
UVICORN_PIDS=$(pgrep -f "$UVICORN_PATTERN" 2>/dev/null || true)
# Combine and deduplicate
ALL_BACKEND_PIDS=$(echo "$BACKEND_PIDS $UVICORN_PIDS" | tr ' ' '\n' | sort -u | tr '\n' ' ' | xargs)
if [ -n "$ALL_BACKEND_PIDS" ]; then
ORPHANS_FOUND=true
log " Found orphaned backend processes: $ALL_BACKEND_PIDS"
for pid in $ALL_BACKEND_PIDS; do
kill_tree "$pid" KILL
done
log " ✓ Killed orphaned backend processes"
fi
# Kill processes on backend port
PORT_BACKEND_PIDS=$(lsof -ti :$BACKEND_PORT 2>/dev/null || true)
if [ -n "$PORT_BACKEND_PIDS" ]; then
ORPHANS_FOUND=true
log " Found processes on port $BACKEND_PORT: $PORT_BACKEND_PIDS"
for pid in $PORT_BACKEND_PIDS; do
kill -9 "$pid" 2>/dev/null || true
done
log " ✓ Killed processes on port $BACKEND_PORT"
fi
# Kill processes on frontend port
PORT_FRONTEND_PIDS=$(lsof -ti :$FRONTEND_PORT 2>/dev/null || true)
if [ -n "$PORT_FRONTEND_PIDS" ]; then
ORPHANS_FOUND=true
log " Found processes on port $FRONTEND_PORT: $PORT_FRONTEND_PIDS"
for pid in $PORT_FRONTEND_PIDS; do
kill -9 "$pid" 2>/dev/null || true
done
log " ✓ Killed processes on port $FRONTEND_PORT"
fi
# Kill nuxt dev processes specifically for this project
# Check if process command line contains our project path
NUXT_PIDS=""
for pid in $(pgrep -f "nuxt.*dev" 2>/dev/null || true); do
# Verify this is for our project by checking cwd or command
if ps -p "$pid" -o args= 2>/dev/null | grep -q "$SCRIPT_DIR" 2>/dev/null; then
NUXT_PIDS="$NUXT_PIDS $pid"
fi
done
NUXT_PIDS=$(echo "$NUXT_PIDS" | xargs)
if [ -n "$NUXT_PIDS" ]; then
ORPHANS_FOUND=true
log " Found orphaned frontend processes: $NUXT_PIDS"
for pid in $NUXT_PIDS; do
kill_tree "$pid" KILL
done
log " ✓ Killed orphaned frontend processes"
fi
# Kill any node processes that might be related to our frontend
# Be more conservative here - only kill if definitely ours
NODE_PIDS=""
for pid in $(pgrep -f "node.*$SCRIPT_DIR/frontend" 2>/dev/null || true); do
NODE_PIDS="$NODE_PIDS $pid"
done
NODE_PIDS=$(echo "$NODE_PIDS" | xargs)
if [ -n "$NODE_PIDS" ]; then
ORPHANS_FOUND=true
log " Found orphaned node processes: $NODE_PIDS"
for pid in $NODE_PIDS; do
kill -9 "$pid" 2>/dev/null || true
done
log " ✓ Killed orphaned node processes"
fi
if [ "$ORPHANS_FOUND" = false ]; then
log " ✓ No orphaned processes found"
fi
log ""
# ============================================
# VERIFICATION: Confirm services are stopped
# ============================================
log "🔍 Verification..."
# Give processes a moment to fully release ports
sleep 1
VERIFICATION_OK=true
# Check backend port
if lsof -ti :$BACKEND_PORT > /dev/null 2>&1; then
log " ⚠️ Port $BACKEND_PORT still in use!"
VERIFICATION_OK=false
else
log " ✓ Port $BACKEND_PORT is free"
fi
# Check frontend port
if lsof -ti :$FRONTEND_PORT > /dev/null 2>&1; then
log " ⚠️ Port $FRONTEND_PORT still in use!"
VERIFICATION_OK=false
else
log " ✓ Port $FRONTEND_PORT is free"
fi
# Check for any remaining processes
REMAINING_BACKEND=$(pgrep -f "$BACKEND_PATTERN" 2>/dev/null || true)
if [ -n "$REMAINING_BACKEND" ]; then
log " ⚠️ Backend processes still running: $REMAINING_BACKEND"
VERIFICATION_OK=false
fi
log ""
# ============================================
# SUMMARY
# ============================================
if [ "$VERIFICATION_OK" = true ]; then
log "========================================"
log "✅ Services Stopped Successfully!"
log "========================================"
else
log "========================================"
log "⚠️ Services Stopped (with warnings)"
log "========================================"
log ""
log "Some processes may still be running. Try:"
log " $0 --force"
log ""
log "Or manually check:"
log " lsof -ti :$BACKEND_PORT"
log " lsof -ti :$FRONTEND_PORT"
fi
log ""