| |
| """ |
| Production database initialization script. |
| This ensures templates are populated properly and verifies database health. |
| SAFE for PostgreSQL/RDS - only creates tables on SQLite databases. |
| """ |
|
|
| import sys |
| import os |
| import logging |
| from datetime import datetime, UTC |
|
|
| |
| sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) |
|
|
| from src.db.init_db import init_db, session_factory, engine, is_postgres_db |
| from src.db.schemas.models import Base, AgentTemplate, UserTemplatePreference |
| from scripts.populate_agent_templates import populate_templates |
| from sqlalchemy import inspect, text |
| from src.utils.logger import Logger |
|
|
| logger = Logger("init_production_db", see_time=True, console_log=True) |
|
|
| def get_database_type(): |
| """Get the database type (sqlite or postgresql).""" |
| try: |
| if is_postgres_db(): |
| return "postgresql" |
| else: |
| return "sqlite" |
| except Exception as e: |
| logger.log_message(f"Error determining database type: {e}", logging.ERROR) |
| return "unknown" |
|
|
| def check_table_exists(table_name: str) -> bool: |
| """Check if a table exists in the database.""" |
| try: |
| inspector = inspect(engine) |
| tables = inspector.get_table_names() |
| return table_name in tables |
| except Exception as e: |
| logger.log_message(f"Error checking table existence: {e}", logging.ERROR) |
| return False |
|
|
| def verify_database_schema(): |
| """Verify that all required tables exist. Only create tables on SQLite.""" |
| db_type = get_database_type() |
| logger.log_message(f"π Verifying database schema for {db_type.upper()} database...", logging.INFO) |
| |
| required_tables = [ |
| 'users', 'chats', 'messages', 'model_usage', 'code_executions', |
| 'message_feedback', 'deep_analysis_reports', 'agent_templates', |
| 'user_template_preferences' |
| ] |
| |
| missing_tables = [] |
| existing_tables = [] |
| |
| for table in required_tables: |
| if not check_table_exists(table): |
| missing_tables.append(table) |
| logger.log_message(f"β Missing table: {table}", logging.WARNING) |
| else: |
| existing_tables.append(table) |
| logger.log_message(f"β
Table exists: {table}", logging.INFO) |
| |
| if missing_tables: |
| if db_type == "sqlite": |
| logger.log_message(f"π§ Creating missing tables on SQLite: {missing_tables}", logging.INFO) |
| try: |
| |
| Base.metadata.create_all(engine) |
| logger.log_message("β
All tables created successfully on SQLite", logging.INFO) |
| except Exception as e: |
| logger.log_message(f"β Failed to create tables: {e}", logging.ERROR) |
| raise |
| else: |
| |
| logger.log_message(f"β οΈ WARNING: Missing tables detected in {db_type.upper()} database: {missing_tables}", logging.WARNING) |
| logger.log_message("π‘οΈ SAFETY: Not creating tables automatically on PostgreSQL/RDS", logging.INFO) |
| logger.log_message("π Please ensure these tables exist in your RDS database:", logging.INFO) |
| for table in missing_tables: |
| logger.log_message(f" - {table}", logging.INFO) |
| |
| |
| if 'agent_templates' in missing_tables or 'user_template_preferences' in missing_tables: |
| logger.log_message("β οΈ Template functionality may not work without agent_templates and user_template_preferences tables", logging.WARNING) |
| else: |
| logger.log_message(f"β
All required tables exist in {db_type.upper()} database", logging.INFO) |
|
|
| def verify_template_data(): |
| """Verify that agent templates are populated. Safe for all database types.""" |
| logger.log_message("π Verifying template data...", logging.INFO) |
| |
| session = session_factory() |
| try: |
| |
| if not check_table_exists('agent_templates'): |
| logger.log_message("β οΈ agent_templates table does not exist, skipping template verification", logging.WARNING) |
| return |
| |
| template_count = session.query(AgentTemplate).filter(AgentTemplate.is_active == True).count() |
| logger.log_message(f"π Found {template_count} active templates", logging.INFO) |
| |
| if template_count == 0: |
| logger.log_message("π§ No templates found, populating...", logging.INFO) |
| try: |
| populate_templates() |
| |
| |
| new_count = session.query(AgentTemplate).filter(AgentTemplate.is_active == True).count() |
| logger.log_message(f"β
Templates populated. Total active templates: {new_count}", logging.INFO) |
| except Exception as e: |
| logger.log_message(f"β Template population failed: {e}", logging.ERROR) |
| logger.log_message("β οΈ App will continue but template functionality may not work", logging.WARNING) |
| else: |
| logger.log_message("β
Templates already populated", logging.INFO) |
| |
| except Exception as e: |
| logger.log_message(f"β Error verifying templates: {e}", logging.ERROR) |
| logger.log_message("β οΈ Template verification failed, but app will continue", logging.WARNING) |
| finally: |
| session.close() |
|
|
| def test_template_api_functionality(): |
| """Test that template-related database operations work. Safe for all database types.""" |
| logger.log_message("π§ͺ Testing template API functionality...", logging.INFO) |
| |
| session = session_factory() |
| try: |
| |
| if not check_table_exists('agent_templates'): |
| logger.log_message("β οΈ agent_templates table does not exist, skipping API test", logging.WARNING) |
| return |
| |
| |
| templates = session.query(AgentTemplate).filter(AgentTemplate.is_active == True).limit(5).all() |
| logger.log_message(f"β
Successfully queried {len(templates)} templates", logging.INFO) |
| |
| if templates: |
| sample_template = templates[0] |
| logger.log_message(f"π Sample template: {sample_template.template_name} - {sample_template.display_name}", logging.INFO) |
| else: |
| logger.log_message("π No templates found in database", logging.INFO) |
| |
| except Exception as e: |
| logger.log_message(f"β Template API test failed: {e}", logging.ERROR) |
| logger.log_message("β οΈ Template API may not work properly", logging.WARNING) |
| finally: |
| session.close() |
|
|
| def run_safe_initialization(): |
| """Run safe database initialization that respects production databases.""" |
| db_type = get_database_type() |
| logger.log_message(f"π Starting SAFE database initialization for {db_type.upper()}...", logging.INFO) |
| |
| if db_type == "postgresql": |
| logger.log_message("π‘οΈ PostgreSQL/RDS detected - running in SAFE mode", logging.INFO) |
| logger.log_message("π Will only verify schema and populate templates", logging.INFO) |
| elif db_type == "sqlite": |
| logger.log_message("π½ SQLite detected - full initialization mode", logging.INFO) |
| |
| try: |
| |
| logger.log_message("Step 1: Basic database initialization", logging.INFO) |
| if db_type == "sqlite": |
| init_db() |
| else: |
| logger.log_message("Skipping init_db() for PostgreSQL (safety)", logging.INFO) |
| |
| |
| logger.log_message("Step 2: Schema verification", logging.INFO) |
| verify_database_schema() |
| |
| |
| logger.log_message("Step 3: Template data verification", logging.INFO) |
| verify_template_data() |
| |
| |
| logger.log_message("Step 4: Functionality testing", logging.INFO) |
| test_template_api_functionality() |
| |
| logger.log_message(f"π Safe database initialization completed for {db_type.upper()}!", logging.INFO) |
| |
| except Exception as e: |
| logger.log_message(f"π₯ Database initialization failed: {e}", logging.ERROR) |
| logger.log_message("β οΈ App may still start but some features might not work", logging.WARNING) |
| |
|
|
| if __name__ == "__main__": |
| run_safe_initialization() |