"""Async database engine and session helpers.""" from collections.abc import AsyncGenerator from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession, async_sessionmaker, create_async_engine from app.config.settings import get_settings from app.infra.db.base import Base _engine: AsyncEngine | None = None _session_factory: async_sessionmaker[AsyncSession] | None = None def get_async_engine() -> AsyncEngine: """Return the lazily created async SQLAlchemy engine.""" global _engine if _engine is None: _engine = create_async_engine( get_settings().database_url, future=True, echo=False, ) return _engine def get_session_factory() -> async_sessionmaker[AsyncSession]: """Return the lazily created async session factory.""" global _session_factory if _session_factory is None: _session_factory = async_sessionmaker(get_async_engine(), expire_on_commit=False) return _session_factory async def get_db_session() -> AsyncGenerator[AsyncSession, None]: """Yield a database session for FastAPI dependencies.""" async with get_session_factory()() as session: yield session async def init_database() -> None: """Create database tables when running the MVP without migrations.""" from app.infra.db.models.asset import AssetORM from app.infra.db.models.order import OrderORM from app.infra.db.models.review_task import ReviewTaskORM from app.infra.db.models.workflow_run import WorkflowRunORM from app.infra.db.models.workflow_step import WorkflowStepORM del AssetORM, OrderORM, ReviewTaskORM, WorkflowRunORM, WorkflowStepORM async with get_async_engine().begin() as connection: await connection.run_sync(Base.metadata.create_all) async def dispose_database() -> None: """Dispose the active engine and clear cached session objects.""" global _engine, _session_factory if _engine is not None: await _engine.dispose() _engine = None _session_factory = None