Не передавайте request-scoped DB-сессию в долгую фоновую задачу. Передайте file_id, а сессию создавайте внутри задачи; для пятиминутного парсинга надёжнее отдельная очередь и worker.
app = FastAPI()
Не передавайте request-scoped DB-сессию в долгую фоновую задачу. Передайте file_id, а сессию создавайте внутри задачи; для пятиминутного парсинга надёжнее отдельная очередь и worker.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
app = FastAPI()
def get_db(): db = SessionLocal() try: yield db finally: db.close()
def heavy_text_parser(file_id: int, db: Session): # Парсинг файла, который длится 5 минут parse_and_save(file_id, db)
@app.post("/upload") async def upload_file( background_tasks: BackgroundTasks, db: Session = Depends(get_db) ): file_id = save_file_to_db(db) db.commit()
background_tasks.add_task(heavy_text_parser, file_id, db)
return {"status": "parsing started"}
Ответ
Не передавайте request-scoped DB-сессию в долгую фоновую задачу. Передайте file_id, а сессию создавайте внутри задачи; для пятиминутного парсинга надёжнее отдельная очередь и worker.
def heavy_text_parser(file_id: int):
with SessionLocal() as db:
try:
parse_and_save(file_id, db)
db.commit()
except Exception:
db.rollback()
raise
# После успешного commit загрузки:
background_tasks.add_task(heavy_text_parser, file_id)
Порядок закрытия yield-зависимостей менялся между версиями FastAPI, поэтому нельзя строить жизненный цикл задачи на этом совпадении. BackgroundTasks исполняется в процессе приложения и не гарантирует переживание перезапуска. Синхронная DB-операция в async-обработчике также блокирует event loop — используйте согласованный sync/async-путь.
Источник: fastapi.tiangolo.com.