"""Database configuration with async SQLAlchemy + pgvector.""" from typing import AsyncGenerator from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine from sqlalchemy.orm import declarative_base from sqlalchemy.pool import NullPool from src.config import settings # Base class for SQLModel/SQLAlchemy models Base = declarative_base() # Engine configuration engine_kwargs = { "pool_size": settings.DATABASE_POOL_SIZE, "max_overflow": settings.DATABASE_MAX_OVERFLOW, "pool_pre_ping": True, "pool_recycle": 300, "echo": settings.DEBUG, } if settings.APP_ENV == "testing": engine_kwargs["poolclass"] = NullPool engine = create_async_engine( settings.database_url_str, **engine_kwargs, ) # Session factory AsyncSessionLocal = async_sessionmaker( engine, class_=AsyncSession, expire_on_commit=False, autoflush=False, autocommit=False, ) async def get_db() -> AsyncGenerator[AsyncSession, None]: """Yield an async database session for dependency injection.""" async with AsyncSessionLocal() as session: try: yield session await session.commit() except Exception: await session.rollback() raise finally: await session.close() async def init_db() -> None: """Initialize database tables (for dev/testing only).""" async with engine.begin() as conn: await conn.run_sync(Base.metadata.create_all) async def close_db() -> None: """Dispose database engine.""" await engine.dispose()