#!/bin/bash # Unified Backend Service Control Script for ROA2WEB # Manages the unified FastAPI backend on port 8000 (Reports + Data Entry + Telegram) # Script directory SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ROOT_DIR="$SCRIPT_DIR" # Source helper functions source "$SCRIPT_DIR/scripts/service-helpers.sh" # Service configuration SERVICE_NAME="Unified Backend" PORT=8000 LOGS_DIR="$ROOT_DIR/logs" LOG_FILE_STDOUT="$LOGS_DIR/backend-stdout.log" LOG_FILE_STDERR="$LOGS_DIR/backend-stderr.log" LOG_FILE="$LOG_FILE_STDERR" # Default for status/logs commands BACKEND_DIR="$ROOT_DIR/backend" VENV_DIR="$BACKEND_DIR/venv" ENV_FILE="$BACKEND_DIR/.env" # Function to start backend start_backend() { print_header "Starting $SERVICE_NAME" # Check if port is already in use if ! check_port_available $PORT "$SERVICE_NAME"; then print_warning "$SERVICE_NAME may already be running" print_info "Use './start-backend.sh status' to check or './start-backend.sh stop' to stop it" return 1 fi # Check backend directory if [ ! -d "$BACKEND_DIR" ]; then print_error "Backend directory not found: $BACKEND_DIR" return 1 fi # Check virtual environment if [ ! -d "$VENV_DIR" ]; then print_info "Creating virtual environment..." cd "$BACKEND_DIR" python3 -m venv venv source venv/bin/activate print_info "Installing dependencies (this may take 3-5 minutes for ML packages)..." pip install -r requirements.txt cd "$ROOT_DIR" fi # Check .env file if [ ! -f "$ENV_FILE" ]; then print_warning ".env file not found: $ENV_FILE" print_info "Using backend/.env.example as template" if [ -f "$BACKEND_DIR/.env.example" ]; then cp "$BACKEND_DIR/.env.example" "$ENV_FILE" print_info "Created $ENV_FILE - please configure it" fi fi # Start backend print_info "Starting unified backend on port $PORT..." cd "$BACKEND_DIR" # Create logs directory if it doesn't exist mkdir -p "$LOGS_DIR" # Clear old log files > "$LOG_FILE_STDOUT" > "$LOG_FILE_STDERR" # Activate virtual environment and start uvicorn # stdout → backend-stdout.log, stderr → backend-stderr.log nohup bash -c "source venv/bin/activate && uvicorn main:app --host 0.0.0.0 --port $PORT --reload" > "$LOG_FILE_STDOUT" 2> "$LOG_FILE_STDERR" & BACKEND_PID=$! cd "$ROOT_DIR" # Wait for backend to start print_info "Waiting for backend to initialize (Oracle pool + cache + databases)..." MAX_WAIT=30 ELAPSED=0 while [ $ELAPSED -lt $MAX_WAIT ]; do if check_port_in_use $PORT; then print_success "$SERVICE_NAME started successfully on http://localhost:$PORT" print_info "Process ID: $BACKEND_PID" print_info "Log file: $LOG_FILE" print_info "API Documentation: http://localhost:$PORT/docs" print_info "Health Check: http://localhost:$PORT/health" echo print_info "Modules:" echo " • Reports API: http://localhost:$PORT/api/reports/*" echo " • Data Entry API: http://localhost:$PORT/api/data-entry/*" echo " • Telegram API: http://localhost:$PORT/api/telegram/*" echo " • Auth API: http://localhost:$PORT/api/auth/*" # Check health endpoint sleep 2 if command -v curl &> /dev/null; then print_info "Checking health endpoint..." curl -s http://localhost:$PORT/health | python3 -m json.tool || echo "(health check pending)" fi return 0 fi sleep 1 ELAPSED=$((ELAPSED + 1)) if [ $((ELAPSED % 5)) -eq 0 ]; then print_info "Still waiting... ($ELAPSED/${MAX_WAIT}s)" fi done print_error "$SERVICE_NAME failed to start within ${MAX_WAIT}s" print_info "Check log file: $LOG_FILE" tail -n 20 "$LOG_FILE" return 1 } # Function to stop backend stop_backend() { print_header "Stopping $SERVICE_NAME" if check_port_in_use $PORT; then print_info "Stopping processes on port $PORT..." # Get PIDs PIDS=$(lsof -ti:$PORT) if [ -n "$PIDS" ]; then # Try graceful shutdown first echo "$PIDS" | xargs kill -TERM 2>/dev/null || true sleep 2 # Force kill if still running if check_port_in_use $PORT; then print_warning "Graceful shutdown failed, forcing..." echo "$PIDS" | xargs kill -KILL 2>/dev/null || true sleep 1 fi if check_port_in_use $PORT; then print_error "Failed to stop $SERVICE_NAME" return 1 else print_success "$SERVICE_NAME stopped" return 0 fi fi else print_info "$SERVICE_NAME is not running" return 0 fi } # Function to restart backend restart_backend() { print_header "Restarting $SERVICE_NAME" stop_backend sleep 2 start_backend } # Function to check backend status status_backend() { print_header "$SERVICE_NAME Status" if check_port_in_use $PORT; then print_success "$SERVICE_NAME is running on port $PORT" # Get process info PIDS=$(lsof -ti:$PORT) print_info "Process IDs: $PIDS" # Show recent log if [ -f "$LOG_FILE" ]; then echo print_info "Recent log entries (last 10 lines):" tail -n 10 "$LOG_FILE" fi # Check health endpoint echo if command -v curl &> /dev/null; then print_info "Health check:" curl -s http://localhost:$PORT/health | python3 -m json.tool || echo "(health endpoint not responding)" fi return 0 else print_warning "$SERVICE_NAME is not running" return 1 fi } # Function to show logs logs_backend() { if [ ! -f "$LOG_FILE" ]; then print_warning "Log file not found: $LOG_FILE" return 1 fi if [ "$1" = "follow" ] || [ "$1" = "-f" ]; then print_info "Following $SERVICE_NAME logs (Ctrl+C to stop)..." tail -f "$LOG_FILE" else print_info "Showing last 50 lines of $SERVICE_NAME logs:" tail -n 50 "$LOG_FILE" fi } # Main script logic case "$1" in start) start_backend ;; stop) stop_backend ;; restart) restart_backend ;; status) status_backend ;; logs) logs_backend "$2" ;; *) echo "Usage: $0 {start|stop|restart|status|logs [follow]}" echo echo "Commands:" echo " start - Start the unified backend (port $PORT)" echo " stop - Stop the unified backend" echo " restart - Restart the unified backend" echo " status - Check if backend is running" echo " logs - Show recent logs" echo " logs follow - Follow logs in real-time" exit 1 ;; esac exit $?