212 lines
5.8 KiB
Bash
Executable file
212 lines
5.8 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
#
|
|
# Conversation Assistant Development Server
|
|
# Manages backend API, ML service, and frontend with proper dependency ordering
|
|
#
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
|
|
|
# Configuration
|
|
BACKEND_PORT="${BACKEND_PORT:-3100}"
|
|
ML_SERVICE_PORT="${ML_SERVICE_PORT:-8100}"
|
|
FRONTEND_PORT="${FRONTEND_PORT:-5173}"
|
|
|
|
# Database configuration (defaults for local dev)
|
|
DB_HOST="${DB_HOST:-localhost}"
|
|
DB_PORT="${DB_PORT:-25432}"
|
|
DB_USER="${DB_USER:-lilith}"
|
|
DB_PASSWORD="${DB_PASSWORD:-lilith}"
|
|
DB_NAME="${DB_NAME:-conversation_assistant}"
|
|
JWT_SECRET="${JWT_SECRET:-dev-secret-testing}"
|
|
ML_SERVICE_URL="${ML_SERVICE_URL:-http://localhost:$ML_SERVICE_PORT}"
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
|
log_success() { echo -e "${GREEN}[OK]${NC} $1"; }
|
|
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
|
|
|
# Check if a port is in use
|
|
port_in_use() {
|
|
local port=$1
|
|
ss -tlnp 2>/dev/null | grep -q ":${port} " && return 0
|
|
return 1
|
|
}
|
|
|
|
# Wait for a service to be healthy
|
|
wait_for_service() {
|
|
local url=$1
|
|
local name=$2
|
|
local max_attempts=${3:-30}
|
|
local attempt=0
|
|
|
|
log_info "Waiting for $name to be ready..."
|
|
while [ $attempt -lt $max_attempts ]; do
|
|
if curl -sf "$url" >/dev/null 2>&1; then
|
|
log_success "$name is ready"
|
|
return 0
|
|
fi
|
|
attempt=$((attempt + 1))
|
|
sleep 1
|
|
done
|
|
|
|
log_error "$name failed to start after ${max_attempts}s"
|
|
return 1
|
|
}
|
|
|
|
# Check PostgreSQL connection
|
|
check_postgres() {
|
|
log_info "Checking PostgreSQL connection..."
|
|
if PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "SELECT 1" >/dev/null 2>&1; then
|
|
log_success "PostgreSQL is available"
|
|
return 0
|
|
else
|
|
log_error "Cannot connect to PostgreSQL at $DB_HOST:$DB_PORT"
|
|
log_info "Make sure PostgreSQL is running with database '$DB_NAME'"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Start ML service if not running
|
|
start_ml_service() {
|
|
if port_in_use "$ML_SERVICE_PORT"; then
|
|
log_success "ML service already running on port $ML_SERVICE_PORT"
|
|
return 0
|
|
fi
|
|
|
|
log_info "Starting ML service on port $ML_SERVICE_PORT..."
|
|
cd "$PROJECT_DIR/ml-service"
|
|
|
|
# Check for virtual environment
|
|
if [ -d ".venv" ]; then
|
|
source .venv/bin/activate
|
|
elif [ -d "venv" ]; then
|
|
source venv/bin/activate
|
|
fi
|
|
|
|
ML_SERVICE_PORT="$ML_SERVICE_PORT" python -m uvicorn main:app --host 0.0.0.0 --port "$ML_SERVICE_PORT" &
|
|
ML_PID=$!
|
|
echo $ML_PID > /tmp/conv-assistant-ml.pid
|
|
|
|
wait_for_service "http://localhost:$ML_SERVICE_PORT/health" "ML service" 60
|
|
}
|
|
|
|
# Start backend API if not running
|
|
start_backend() {
|
|
if port_in_use "$BACKEND_PORT"; then
|
|
log_success "Backend API already running on port $BACKEND_PORT"
|
|
return 0
|
|
fi
|
|
|
|
log_info "Starting backend API on port $BACKEND_PORT..."
|
|
cd "$PROJECT_DIR/backend-api"
|
|
|
|
# Export environment variables
|
|
export PORT="$BACKEND_PORT"
|
|
export DB_HOST DB_PORT DB_USER DB_PASSWORD DB_NAME
|
|
export JWT_SECRET
|
|
export ML_SERVICE_URL
|
|
|
|
pnpm start:dev &
|
|
BACKEND_PID=$!
|
|
echo $BACKEND_PID > /tmp/conv-assistant-backend.pid
|
|
|
|
wait_for_service "http://localhost:$BACKEND_PORT/api" "Backend API" 60
|
|
}
|
|
|
|
# Start frontend
|
|
start_frontend() {
|
|
if port_in_use "$FRONTEND_PORT"; then
|
|
log_warn "Frontend already running on port $FRONTEND_PORT"
|
|
log_info "Visit http://localhost:$FRONTEND_PORT"
|
|
return 0
|
|
fi
|
|
|
|
log_info "Starting frontend on port $FRONTEND_PORT..."
|
|
cd "$PROJECT_DIR/frontend-dev"
|
|
|
|
# Frontend runs in foreground so user can see output and Ctrl+C
|
|
exec pnpm dev
|
|
}
|
|
|
|
# Cleanup function for graceful shutdown
|
|
cleanup() {
|
|
log_info "Shutting down services..."
|
|
|
|
# Kill backend if we started it
|
|
if [ -f /tmp/conv-assistant-backend.pid ]; then
|
|
kill "$(cat /tmp/conv-assistant-backend.pid)" 2>/dev/null || true
|
|
rm -f /tmp/conv-assistant-backend.pid
|
|
fi
|
|
|
|
# Kill ML service if we started it
|
|
if [ -f /tmp/conv-assistant-ml.pid ]; then
|
|
kill "$(cat /tmp/conv-assistant-ml.pid)" 2>/dev/null || true
|
|
rm -f /tmp/conv-assistant-ml.pid
|
|
fi
|
|
|
|
log_success "Cleanup complete"
|
|
}
|
|
|
|
# Main execution
|
|
main() {
|
|
trap cleanup EXIT INT TERM
|
|
|
|
echo ""
|
|
echo "=========================================="
|
|
echo " Conversation Assistant Dev Server"
|
|
echo "=========================================="
|
|
echo ""
|
|
|
|
# Check dependencies
|
|
check_postgres || exit 1
|
|
|
|
# Start services in order
|
|
start_ml_service || log_warn "ML service not available (AI features disabled)"
|
|
start_backend || exit 1
|
|
|
|
echo ""
|
|
log_success "All services ready!"
|
|
echo ""
|
|
echo " Backend API: http://localhost:$BACKEND_PORT/api"
|
|
echo " ML Service: http://localhost:$ML_SERVICE_PORT"
|
|
echo " Frontend: http://localhost:$FRONTEND_PORT"
|
|
echo ""
|
|
echo "Press Ctrl+C to stop all services"
|
|
echo ""
|
|
|
|
# Start frontend (foreground, blocks until Ctrl+C)
|
|
start_frontend
|
|
}
|
|
|
|
# Handle command-line arguments
|
|
case "${1:-}" in
|
|
--backend-only)
|
|
check_postgres || exit 1
|
|
start_backend
|
|
wait
|
|
;;
|
|
--frontend-only)
|
|
start_frontend
|
|
;;
|
|
--status)
|
|
echo "Service Status:"
|
|
port_in_use "$BACKEND_PORT" && echo " Backend API: running" || echo " Backend API: stopped"
|
|
port_in_use "$ML_SERVICE_PORT" && echo " ML Service: running" || echo " ML Service: stopped"
|
|
port_in_use "$FRONTEND_PORT" && echo " Frontend: running" || echo " Frontend: stopped"
|
|
;;
|
|
--stop)
|
|
cleanup
|
|
;;
|
|
*)
|
|
main
|
|
;;
|
|
esac
|