from __future__ import annotations from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession, async_sessionmaker, create_async_engine from .config import Config _engine: AsyncEngine | None = None _sessionmaker: async_sessionmaker[AsyncSession] | None = None def get_engine() -> AsyncEngine: """Lazily create the process-wide async engine. Lazy so the app (and unit tests) can import/boot without a live database — only routes that actually touch data open a connection. """ global _engine, _sessionmaker if _engine is None: _engine = create_async_engine(Config.DATABASE_URL, pool_pre_ping=True) _sessionmaker = async_sessionmaker(_engine, expire_on_commit=False) return _engine def get_sessionmaker() -> async_sessionmaker[AsyncSession]: if _sessionmaker is None: get_engine() assert _sessionmaker is not None return _sessionmaker def session_scope() -> AsyncSession: """Open a new AsyncSession. Use as `async with session_scope() as db: ...`.""" return get_sessionmaker()() async def dispose_engine() -> None: global _engine, _sessionmaker if _engine is not None: await _engine.dispose() _engine = None _sessionmaker = None