perf(api): run heavy endpoints in the threadpool (stop freezing the web GUI)
Blocking operations (SMTP send loops, Wazuh/Nessus/Graph HTTP, bulk re-scoring) were declared `async def` but do synchronous work inline, so they ran ON the event loop and froze the entire web GUI until they finished (tester: "Notify All Critical/High" locks TrueVuln the whole time, and the same at many other places). Converted the offending endpoints to plain `def` so Starlette runs them in a worker threadpool off the event loop — the GUI stays responsive while they run. Verified each has no `await` in its body before converting (mechanical, behaviour-preserving): - notifications: notify-critical (the reported one), test email - assets: coverage-gap, refresh-exposure, sync-wazuh-assets, rescan-asset - scans: trigger-autoscan - vulnerabilities: enrich-single, refresh-kev-catalog, wazuh sync, override-from-nessus, recompute-priority-scores - nessus: test-connection, list-scans, scan-host (Several other heavy endpoints — m365-check, eol-check, exploit-intel, bulk-enrich, nessus /sync, app-cve-scan, suppress-fp — were already sync def from earlier in this work.)
This commit is contained in:
@@ -202,7 +202,7 @@ async def reconcile_lifecycle(
|
||||
|
||||
|
||||
@router.get("/{asset_id}/coverage-gap")
|
||||
async def asset_coverage_gap(
|
||||
def asset_coverage_gap(
|
||||
asset_id: int,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user),
|
||||
@@ -301,7 +301,7 @@ async def asset_coverage_gap(
|
||||
|
||||
|
||||
@router.post("/refresh-exposure")
|
||||
async def refresh_exposure(
|
||||
def refresh_exposure(
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user),
|
||||
):
|
||||
@@ -740,7 +740,7 @@ from app.integrations.wazuh_client import WazuhClient, WazuhAPIError
|
||||
from app.models.setting import Setting
|
||||
|
||||
@router.post("/sync_wazuh", response_model=dict)
|
||||
async def sync_wazuh_assets(
|
||||
def sync_wazuh_assets(
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(RequireEditor)
|
||||
):
|
||||
@@ -871,7 +871,7 @@ async def sync_wazuh_assets(
|
||||
|
||||
|
||||
@router.post("/{asset_id}/rescan", response_model=dict)
|
||||
async def rescan_asset(
|
||||
def rescan_asset(
|
||||
asset_id: int,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(RequireEditor)
|
||||
|
||||
@@ -65,7 +65,7 @@ class NessusScanImportRequest(BaseModel):
|
||||
|
||||
# ---------- endpoints ----------
|
||||
@router.post("/test")
|
||||
async def test_nessus_connection(
|
||||
def test_nessus_connection(
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(RequireAdmin),
|
||||
):
|
||||
@@ -103,7 +103,7 @@ async def test_nessus_connection(
|
||||
|
||||
|
||||
@router.get("/scans")
|
||||
async def list_nessus_scans(
|
||||
def list_nessus_scans(
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(RequireEditor),
|
||||
):
|
||||
@@ -177,7 +177,7 @@ def trigger_nessus_sync(
|
||||
|
||||
|
||||
@router.post("/scan-host")
|
||||
async def nessus_scan_host(
|
||||
def nessus_scan_host(
|
||||
payload: NessusScanHostRequest,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(RequireEditor),
|
||||
|
||||
@@ -100,7 +100,8 @@ async def list_notification_logs(
|
||||
|
||||
|
||||
@router.post("/test")
|
||||
async def send_test_email(
|
||||
# Sync def → threadpool; the blocking SMTP send won't stall the event loop.
|
||||
def send_test_email(
|
||||
test_data: TestEmailRequest,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(RequireAdmin)
|
||||
@@ -133,7 +134,9 @@ async def send_test_email(
|
||||
|
||||
|
||||
@router.post("/notify-critical")
|
||||
async def notify_unnotified_critical_vulnerabilities(
|
||||
# Sync def → Starlette runs it in a worker threadpool (off the event loop), so
|
||||
# the blocking SMTP send loop over thousands of CVEs doesn't freeze the web GUI.
|
||||
def notify_unnotified_critical_vulnerabilities(
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(RequireAdmin)
|
||||
):
|
||||
|
||||
@@ -227,7 +227,7 @@ from app.integrations.wazuh_client import WazuhClient, WazuhAPIError
|
||||
from app.models.setting import Setting
|
||||
|
||||
@router.post("/autoscan", response_model=dict)
|
||||
async def trigger_autoscan(
|
||||
def trigger_autoscan(
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(RequireEditor)
|
||||
):
|
||||
|
||||
@@ -1346,7 +1346,7 @@ def analyze_vulnerability_with_ai(
|
||||
|
||||
|
||||
@router.post("/{vuln_id}/enrich")
|
||||
async def enrich_single_vulnerability(
|
||||
def enrich_single_vulnerability(
|
||||
vuln_id: int,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(RequireEditor)
|
||||
@@ -1490,7 +1490,7 @@ async def backfill_cve_dates(
|
||||
|
||||
|
||||
@router.post("/enrich/kev/refresh")
|
||||
async def refresh_kev_catalog(
|
||||
def refresh_kev_catalog(
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(RequireEditor)
|
||||
):
|
||||
@@ -1653,7 +1653,7 @@ async def unmark_false_positive(
|
||||
|
||||
|
||||
@router.post("/sync/wazuh")
|
||||
async def sync_vulnerabilities_from_wazuh(
|
||||
def sync_vulnerabilities_from_wazuh(
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(RequireEditor)
|
||||
):
|
||||
@@ -2343,7 +2343,7 @@ async def check_incorrect_scores(
|
||||
|
||||
|
||||
@router.post("/override/nessus/{asset_id}")
|
||||
async def override_from_nessus(
|
||||
def override_from_nessus(
|
||||
asset_id: int,
|
||||
scan_id: Optional[int] = None,
|
||||
dry_run: bool = Query(True, description="Nur simulieren ohne DB-Änderungen"),
|
||||
@@ -3036,7 +3036,7 @@ async def refresh_msrc_endpoint(
|
||||
|
||||
|
||||
@router.post("/recompute-scores")
|
||||
async def recompute_priority_scores(
|
||||
def recompute_priority_scores(
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(RequireEditor),
|
||||
):
|
||||
|
||||
Reference in New Issue
Block a user