| import os |
| from sqlalchemy import create_engine, text |
| from sqlalchemy.ext.declarative import declarative_base |
| from sqlalchemy.orm import sessionmaker |
| from sqlalchemy.exc import SQLAlchemyError, OperationalError |
| from dotenv import load_dotenv |
| import logging |
|
|
| |
| logger = logging.getLogger(__name__) |
|
|
| |
| load_dotenv() |
|
|
| |
| DEFAULT_DB_URL = os.getenv("AIVEN_DB_URL") |
| |
| |
| DB_CONNECTION_MODE = os.getenv("DB_CONNECTION_MODE", "aiven") |
|
|
| |
| if DB_CONNECTION_MODE == "aiven": |
| DATABASE_URL = os.getenv("AIVEN_DB_URL", DEFAULT_DB_URL) |
| else: |
| |
| DATABASE_URL = os.getenv("AIVEN_DB_URL", DEFAULT_DB_URL) |
|
|
| if not DATABASE_URL: |
| logger.error("No database URL configured. Using default URL.") |
| DATABASE_URL = DEFAULT_DB_URL |
|
|
| |
| try: |
| engine = create_engine( |
| DATABASE_URL, |
| pool_size=10, |
| max_overflow=5, |
| pool_timeout=30, |
| pool_recycle=300, |
| pool_pre_ping=True, |
| connect_args={ |
| "connect_timeout": 5, |
| "keepalives": 1, |
| "keepalives_idle": 30, |
| "keepalives_interval": 10, |
| "keepalives_count": 5, |
| "application_name": "pixagent_api" |
| }, |
| |
| isolation_level="READ COMMITTED", |
| echo=False, |
| echo_pool=False, |
| future=True, |
| |
| execution_options={ |
| "compiled_cache": {}, |
| "logging_token": "SQL", |
| } |
| ) |
| logger.info("PostgreSQL engine initialized with optimized settings") |
| except Exception as e: |
| logger.error(f"Failed to initialize PostgreSQL engine: {e}") |
| |
|
|
| |
| SessionLocal = sessionmaker( |
| autocommit=False, |
| autoflush=False, |
| bind=engine, |
| expire_on_commit=False |
| ) |
|
|
| |
| from sqlalchemy.orm import declarative_base |
| Base = declarative_base() |
|
|
| |
| def check_db_connection(): |
| """Check PostgreSQL connection status""" |
| try: |
| |
| with engine.connect() as connection: |
| connection.execute(text("SELECT 1")).fetchone() |
| logger.info("PostgreSQL connection successful") |
| return True |
| except OperationalError as e: |
| logger.error(f"PostgreSQL connection failed: {e}") |
| return False |
| except Exception as e: |
| logger.error(f"Unknown error checking PostgreSQL connection: {e}") |
| return False |
|
|
| |
| def get_db(): |
| """Get PostgreSQL database session""" |
| db = SessionLocal() |
| try: |
| |
| db.execute(text("SELECT 1")).fetchone() |
| yield db |
| except Exception as e: |
| logger.error(f"DB connection error: {e}") |
| raise |
| finally: |
| db.close() |
|
|
| |
| def create_tables(): |
| """Create tables in database""" |
| try: |
| Base.metadata.create_all(bind=engine) |
| logger.info("Database tables created or already exist") |
| return True |
| except SQLAlchemyError as e: |
| logger.error(f"Failed to create database tables (SQLAlchemy error): {e}") |
| return False |
| except Exception as e: |
| logger.error(f"Failed to create database tables (unexpected error): {e}") |
| return False |
|
|
| |
| def create_indexes(): |
| """Create indexes for better query performance""" |
| try: |
| with engine.connect() as conn: |
| try: |
| |
| conn.execute(text(""" |
| CREATE INDEX idx_event_featured |
| ON event_item(featured) |
| """)) |
| except SQLAlchemyError: |
| logger.info("Index idx_event_featured already exists") |
| |
| try: |
| |
| conn.execute(text(""" |
| CREATE INDEX idx_event_active |
| ON event_item(is_active) |
| """)) |
| except SQLAlchemyError: |
| logger.info("Index idx_event_active already exists") |
| |
| try: |
| |
| conn.execute(text(""" |
| CREATE INDEX idx_event_date_start |
| ON event_item(date_start) |
| """)) |
| except SQLAlchemyError: |
| logger.info("Index idx_event_date_start already exists") |
| |
| try: |
| |
| conn.execute(text(""" |
| CREATE INDEX idx_event_featured_active |
| ON event_item(featured, is_active) |
| """)) |
| except SQLAlchemyError: |
| logger.info("Index idx_event_featured_active already exists") |
| |
| |
| try: |
| |
| conn.execute(text(""" |
| CREATE INDEX idx_faq_active |
| ON faq_item(is_active) |
| """)) |
| except SQLAlchemyError: |
| logger.info("Index idx_faq_active already exists") |
| |
| try: |
| |
| conn.execute(text(""" |
| CREATE INDEX idx_emergency_active |
| ON emergency_item(is_active) |
| """)) |
| except SQLAlchemyError: |
| logger.info("Index idx_emergency_active already exists") |
| |
| try: |
| conn.execute(text(""" |
| CREATE INDEX idx_emergency_priority |
| ON emergency_item(priority) |
| """)) |
| except SQLAlchemyError: |
| logger.info("Index idx_emergency_priority already exists") |
| |
| conn.commit() |
| |
| logger.info("Database indexes created or verified") |
| return True |
| except SQLAlchemyError as e: |
| logger.error(f"Failed to create indexes: {e}") |
| return False |