"""Async database engine, session factory, and the FastAPI session dependency. The repository layer builds on ``get_session``; ``get_engine`` also backs the readiness probe. Everything is lazy so importing the app never opens a connection (important for tests and for ``--help``-style invocations). """ from collections.abc import AsyncIterator from sqlalchemy.ext.asyncio import ( AsyncEngine, AsyncSession, async_sessionmaker, create_async_engine, ) from app.core.config import get_settings _engine: AsyncEngine | None = None _sessionmaker: async_sessionmaker[AsyncSession] | None = None def get_engine() -> AsyncEngine: global _engine if _engine is None: _engine = create_async_engine(get_settings().database_url, pool_pre_ping=True) return _engine def get_sessionmaker() -> async_sessionmaker[AsyncSession]: global _sessionmaker if _sessionmaker is None: _sessionmaker = async_sessionmaker( get_engine(), expire_on_commit=False, class_=AsyncSession ) return _sessionmaker async def get_session() -> AsyncIterator[AsyncSession]: """FastAPI dependency. One session per request; commits are explicit in the service layer.""" async with get_sessionmaker()() as session: yield session