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 collections.abc import Awaitable, Callable
|
||||||
|
|
||||||
from fastapi import Request
|
from fastapi import Request
|
||||||
|
from fastapi.concurrency import run_in_threadpool
|
||||||
from fastapi.responses import Response
|
from fastapi.responses import Response
|
||||||
from sqlalchemy import text
|
from sqlalchemy import text
|
||||||
|
|
||||||
|
|
@ -171,10 +172,16 @@ async def audit_log_middleware(
|
||||||
# но если мы тут — нечего атрибутировать, аудит пропускаем.
|
# но если мы тут — нечего атрибутировать, аудит пропускаем.
|
||||||
return response
|
return response
|
||||||
|
|
||||||
# Write после готового response — off the critical path. Любой сбой внутри
|
# Write после готового response — off the critical path для САМОГО клиента
|
||||||
# write_audit_row проглатывается там же; здесь дополнительная страховка.
|
# (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:
|
try:
|
||||||
write_audit_row(
|
await run_in_threadpool(
|
||||||
|
write_audit_row,
|
||||||
username=username,
|
username=username,
|
||||||
action=action,
|
action=action,
|
||||||
method=request.method,
|
method=request.method,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue