feat: Migrate to ultrathin monolith architecture
Consolidate 3 separate applications (reports-app, data-entry-app, telegram-bot) into a unified
architecture with single backend and frontend:
Backend Changes:
- Unified FastAPI backend at backend/ with modular structure
- Modules: reports, data_entry, telegram in backend/modules/
- Centralized config.py and main.py with all routers registered
- Single worker mode (--workers 1) for Telegram bot compatibility
- Shared Oracle connection pool and JWT authentication
- Unified requirements.txt and environment configuration
Frontend Changes:
- Single Vue.js SPA with module-based routing
- Unified frontend at src/ with modules in src/modules/{reports,data-entry}/
- Shared components and stores in src/shared/
- Error boundaries for module isolation
- Dual API proxy in Vite for module communication
Infrastructure:
- New unified startup scripts: start-prod.sh, start-test.sh, start-backend.sh
- Environment templates: .env.dev.example, .env.test.example, .env.prod.example
- Updated deployment scripts for Windows IIS
- Simplified SSH tunnel management
Documentation:
- Comprehensive CLAUDE.md with architecture overview
- Module-specific docs in docs/{data-entry,telegram}/
- Architecture decision records in docs/ARCHITECTURE-DECISIONS.md
- Deployment guides consolidated in deployment/windows/docs/
This migration reduces complexity, improves maintainability, and enables easier
deployment while maintaining all existing functionality.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
231
start-backend.sh
Normal file
231
start-backend.sh
Normal file
@@ -0,0 +1,231 @@
|
||||
#!/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
|
||||
LOG_FILE="/tmp/unified-backend.log"
|
||||
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"
|
||||
|
||||
# Activate virtual environment and start uvicorn
|
||||
nohup bash -c "source venv/bin/activate && uvicorn main:app --host 0.0.0.0 --port $PORT --reload" > "$LOG_FILE" 2>&1 &
|
||||
|
||||
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 $?
|
||||
Reference in New Issue
Block a user