Где вызывается контекстный менеджер для соединения с базой в FastAPI
Что проверяют
Знаете ли вы механизм зависимостей с yield и понимаете ли, где в FastAPI живёт жизненный цикл ресурсов: сессия на запрос и пул на всё приложение. Следом спрашивают, где делать commit и rollback и что будет с сессией в фоновой задаче.
Как отвечать
Контекстных менеджеров обычно два, назвать стоит оба:
lifespanприложения: функция с@asynccontextmanager, передаётся вFastAPI(lifespan=...). Доyieldсоздаётся движокcreate_async_engineс пулом соединений, послеyieldвызываетсяawait engine.dispose(). Обработчики@app.on_event("startup")объявлены устаревшими;- зависимость на запрос: генератор, который FastAPI сам оборачивает в контекстный менеджер. Внутри
async with SessionLocal() as session: yield session, гдеSessionLocal = async_sessionmaker(engine, expire_on_commit=False). Обработчик получает сессию черезAnnotated[AsyncSession, Depends(get_db)], а код послеyieldзакрывает её и возвращает соединение в пул.
Транзакцию удобно держать там же: async with session.begin() закоммитит при успехе и откатит при исключении. expire_on_commit=False для асинхронной сессии важен: иначе обращение к атрибуту после коммита запустит ленивую загрузку и упадёт с MissingGreenlet.
Если спросят, когда именно выполняется код после yield, до отправки ответа или после, скажите честно: это менялось между версиями FastAPI, а в свежих момент выхода задаётся параметром scope у Depends.
Где спотыкаются
Создают движок внутри зависимости. Тогда на каждый запрос новый пул, и под нагрузкой соединения к PostgreSQL заканчиваются.
Передают сессию из зависимости в BackgroundTasks: задача получает закрытую сессию или держит соединение дольше нужного. Фоновой задаче лучше открыть свою.
Смешивают синхронный драйвер с async def: синхронная сессия в асинхронном обработчике блокирует цикл событий. Либо asyncpg и AsyncSession, либо обычный def, который FastAPI выполнит в пуле потоков.