From bdb3f6a6a24f008e94997e24b81f57aa8e897152 Mon Sep 17 00:00:00 2001 From: Bill Date: Sun, 2 Nov 2025 15:32:53 -0500 Subject: [PATCH] refactor: move database initialization from entrypoint to application Move database initialization logic from shell script to Python application lifespan, following separation of concerns and improving maintainability. Benefits: - Single source of truth for database initialization (api/main.py lifespan) - Better testability - Python code vs shell scripts - Clearer logging with structured messages - Easier to debug and maintain - Infrastructure (entrypoint.sh) focuses on service orchestration - Application (api/main.py) owns its data layer Changes: - Removed database init from entrypoint.sh - Enhanced lifespan function with detailed logging - Simplified entrypoint script (now 4 steps instead of 5) - All tests pass (28/28 API endpoint tests) --- api/main.py | 10 +++++++++- entrypoint.sh | 25 ++++--------------------- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/api/main.py b/api/main.py index 39d5c24..ae225b0 100644 --- a/api/main.py +++ b/api/main.py @@ -135,19 +135,27 @@ def create_app( from api.database import initialize_dev_database, initialize_database # Startup - use closure to access db_path from create_app scope + logger.info("🚀 FastAPI application starting...") + logger.info("📊 Initializing database...") + if is_dev_mode(): # Initialize dev database (reset unless PRESERVE_DEV_DATA=true) + logger.info(" 🔧 DEV mode detected - initializing dev database") dev_db_path = get_db_path(db_path) initialize_dev_database(dev_db_path) log_dev_mode_startup_warning() else: # Ensure production database schema exists + logger.info(" 🏭 PROD mode - ensuring database schema exists") initialize_database(db_path) + logger.info("✅ Database initialized") + logger.info("🌐 API server ready to accept requests") + yield # Shutdown (if needed in future) - pass + logger.info("🛑 FastAPI application shutting down...") app = FastAPI( title="AI-Trader Simulation API", diff --git a/entrypoint.sh b/entrypoint.sh index dc9f9f6..571ef28 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -36,24 +36,7 @@ fi echo "✅ Environment variables validated" -# Step 1: Initialize database (respecting dev/prod mode) -echo "📊 Initializing database..." -python -c " -from tools.deployment_config import is_dev_mode, get_db_path -from api.database import initialize_dev_database, initialize_database - -db_path = 'data/jobs.db' -if is_dev_mode(): - print(' 🔧 DEV mode detected - initializing dev database') - dev_db_path = get_db_path(db_path) - initialize_dev_database(dev_db_path) -else: - print(' 🏭 PROD mode - initializing production database') - initialize_database(db_path) -" -echo "✅ Database initialized" - -# Step 2: Merge and validate configuration +# Step 1: Merge and validate configuration echo "🔧 Merging and validating configuration..." python -c "from tools.config_merger import merge_and_validate; merge_and_validate()" || { echo "❌ Configuration validation failed" @@ -62,7 +45,7 @@ python -c "from tools.config_merger import merge_and_validate; merge_and_validat export CONFIG_PATH=/tmp/runtime_config.json echo "✅ Configuration validated and merged" -# Step 3: Start MCP services in background +# Step 2: Start MCP services in background echo "🔧 Starting MCP services..." cd /app python agent_tools/start_mcp_services.py & @@ -71,11 +54,11 @@ MCP_PID=$! # Setup cleanup trap before starting uvicorn trap "echo '🛑 Stopping services...'; kill $MCP_PID 2>/dev/null; exit 0" EXIT SIGTERM SIGINT -# Step 4: Wait for services to initialize +# Step 3: Wait for services to initialize echo "⏳ Waiting for MCP services to start..." sleep 3 -# Step 5: Start FastAPI server with uvicorn (this blocks) +# Step 4: Start FastAPI server with uvicorn (this blocks) # Note: Container always uses port 8080 internally # The API_PORT env var only affects the host port mapping in docker-compose.yml echo "🌐 Starting FastAPI server on port 8080..."