fix(audit): run_in_threadpool для write_audit_row в async middleware (#1202) #1252
1 changed files with 10 additions and 3 deletions
|
|
@ -37,6 +37,7 @@ import re
|
|||
from collections.abc import Awaitable, Callable
|
||||
|
||||
from fastapi import Request
|
||||
from fastapi.concurrency import run_in_threadpool
|
||||
from fastapi.responses import Response
|
||||
from sqlalchemy import text
|
||||
|
||||
|
|
@ -171,10 +172,16 @@ async def audit_log_middleware(
|
|||
# но если мы тут — нечего атрибутировать, аудит пропускаем.
|
||||
return response
|
||||
|
||||
# Write после готового response — off the critical path. Любой сбой внутри
|
||||
# write_audit_row проглатывается там же; здесь дополнительная страховка.
|
||||
# Write после готового response — off the critical path для САМОГО клиента
|
||||
# (response уже отдан выше), но БЛОКИРУЕТ event loop пока идёт sync DB
|
||||
# round-trip (SessionLocal/execute/commit). Это останавливает ВСЕ другие
|
||||
# запросы на loop'е до завершения insert'а — а при исчерпании connection
|
||||
# pool checkout ждёт `pool_timeout=30s` НА loop'е, замораживая весь API
|
||||
# включая /health (#1202). Выполняем write в threadpool через
|
||||
# `run_in_threadpool` — sync IO в worker-потоке, event loop свободен.
|
||||
try:
|
||||
write_audit_row(
|
||||
await run_in_threadpool(
|
||||
write_audit_row,
|
||||
username=username,
|
||||
action=action,
|
||||
method=request.method,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue