from collections.abc import AsyncIterator from contextlib import asynccontextmanager from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine # from fastapi_users.db import SQLAlchemyUserDatabase, SQLAlchemyBaseUserTableUUID from src.core.config import settings engine = create_async_engine( settings.OPENBAO.DATABASE.DATABASE_URL, connect_args={"server_settings": {"search_path": "dkb"}} ) async_session_maker = async_sessionmaker(engine, class_=AsyncSession, expire_on_commit=False) async def get_async_session() -> AsyncIterator[AsyncSession]: """Сессия запроса = одна транзакция: commit при успешном ответе, rollback при любом исключении (R-1, design #12). В маршрутах объявляется только через `src.api.dependencies.db.SessionDep` (`scope="function"`): тогда commit выполняется до отправки ответа, а все зависимости запроса получают одну и ту же сессию. """ async with async_session_maker() as session, session.begin(): yield session @asynccontextmanager async def session_transaction( maker: async_sessionmaker[AsyncSession] | None = None, ) -> AsyncIterator[AsyncSession]: """Отдельная короткая транзакция вне сессии запроса (аудит входа): commit на выходе, rollback при исключении. `maker` по умолчанию — `async_session_maker` приложения (читается при вызове: тесты его подменяют). """ async with (maker or async_session_maker)() as session, session.begin(): yield session