Spaces:
Sleeping
Sleeping
| """ | |
| Database Configuration and Session Management | |
| """ | |
| import logging | |
| from contextlib import contextmanager | |
| from sqlalchemy import create_engine, event, exc | |
| from sqlalchemy.ext.declarative import declarative_base | |
| from sqlalchemy.orm import sessionmaker, Session | |
| from sqlalchemy.pool import QueuePool, NullPool | |
| from sqlalchemy.engine import Engine | |
| from app.config import settings | |
| logger = logging.getLogger(__name__) | |
| # Determine pool class based on database type | |
| # SQLite doesn't support connection pooling, use NullPool | |
| if settings.DATABASE_URL.startswith("sqlite"): | |
| poolclass = NullPool | |
| connect_args = {"check_same_thread": False} | |
| pool_pre_ping = False | |
| else: | |
| poolclass = QueuePool | |
| connect_args = {} | |
| pool_pre_ping = True | |
| # Build engine kwargs; NullPool does not accept pool_size/max_overflow/pool_timeout | |
| _engine_kwargs: dict = dict( | |
| poolclass=poolclass, | |
| pool_pre_ping=pool_pre_ping, | |
| echo=settings.DEBUG, | |
| connect_args=connect_args, | |
| ) | |
| if poolclass is not NullPool: | |
| _engine_kwargs.update( | |
| pool_size=10, | |
| max_overflow=20, | |
| pool_recycle=3600, | |
| pool_timeout=30, | |
| ) | |
| engine = create_engine(settings.DATABASE_URL, **_engine_kwargs) | |
| # Session factory | |
| SessionLocal = sessionmaker( | |
| autocommit=False, | |
| autoflush=False, | |
| bind=engine, | |
| expire_on_commit=False | |
| ) | |
| Base = declarative_base() | |
| def set_sqlite_pragma(dbapi_conn, connection_record): | |
| """ | |
| Set SQLite pragmas for better performance and foreign key support | |
| """ | |
| if settings.DATABASE_URL.startswith("sqlite"): | |
| cursor = dbapi_conn.cursor() | |
| cursor.execute("PRAGMA foreign_keys=ON") | |
| cursor.execute("PRAGMA journal_mode=WAL") | |
| cursor.execute("PRAGMA synchronous=NORMAL") | |
| cursor.close() | |
| def receive_checkout(dbapi_conn, connection_record, connection_proxy): | |
| """ | |
| Log connection checkout events | |
| """ | |
| if settings.DEBUG: | |
| logger.debug("Connection checked out from pool") | |
| def get_db(): | |
| """ | |
| Database session dependency for FastAPI | |
| Yields: | |
| Session: SQLAlchemy database session | |
| Example: | |
| ```python | |
| @app.get("/items") | |
| def get_items(db: Session = Depends(get_db)): | |
| return db.query(Item).all() | |
| ``` | |
| """ | |
| db = SessionLocal() | |
| try: | |
| yield db | |
| except exc.SQLAlchemyError as e: | |
| logger.error(f"Database error: {str(e)}") | |
| db.rollback() | |
| raise | |
| finally: | |
| db.close() | |
| def get_db_context(): | |
| """ | |
| Context manager for database sessions (for use outside FastAPI) | |
| Yields: | |
| Session: SQLAlchemy database session | |
| Example: | |
| ```python | |
| with get_db_context() as db: | |
| items = db.query(Item).all() | |
| ``` | |
| """ | |
| db = SessionLocal() | |
| try: | |
| yield db | |
| db.commit() | |
| except exc.SQLAlchemyError as e: | |
| logger.error(f"Database error: {str(e)}") | |
| db.rollback() | |
| raise | |
| finally: | |
| db.close() | |
| def init_db(): | |
| """ | |
| Initialize database by creating all tables | |
| """ | |
| try: | |
| Base.metadata.create_all(bind=engine) | |
| logger.info("Database tables created successfully") | |
| except Exception as e: | |
| logger.error(f"Error creating database tables: {str(e)}") | |
| raise | |
| def check_db_connection() -> bool: | |
| """ | |
| Check if database connection is healthy | |
| Returns: | |
| bool: True if connection is healthy, False otherwise | |
| """ | |
| try: | |
| from sqlalchemy import text | |
| with engine.connect() as conn: | |
| conn.execute(text("SELECT 1")) | |
| return True | |
| except Exception as e: | |
| logger.error(f"Database connection check failed: {str(e)}") | |
| return False | |