perf: migrate hot-path JSON serialization to orjson

stdlib json was FastAPI's default. Every response body, every SSE frame,
and every add_log/state/payload write paid the stdlib encode cost.

- pyproject.toml: add orjson>=3.10 as a core dep.
- decnet/web/api.py: default_response_class=ORJSONResponse on the
  FastAPI app, so every endpoint return goes through orjson without
  touching call sites. Explicit JSONResponse sites in the validation
  exception handlers migrated to ORJSONResponse for consistency.
- health endpoint's explicit JSONResponse → ORJSONResponse.
- SSE stream (api_stream_events.py): 6 json.dumps call sites →
  orjson.dumps(...).decode() — the per-event frames that fire on every
  sse tick.
- sqlmodel_repo.py: encode sites on the log-insert path switched to
  orjson (fields, payload, state value). Parser sites (json.loads)
  left as-is for now — not on the measured hot path.
This commit is contained in:
2026-04-17 15:07:28 -04:00
parent f1e14280c0
commit 32340bea0d
5 changed files with 26 additions and 21 deletions

View File

@@ -3,7 +3,7 @@ import time
from typing import Any, Optional
from fastapi import APIRouter, Depends
from fastapi.responses import JSONResponse
from fastapi.responses import ORJSONResponse
from decnet.telemetry import traced as _traced
from decnet.web.dependencies import require_viewer, repo
@@ -138,4 +138,4 @@ async def get_health(user: dict = Depends(require_viewer)) -> Any:
result = HealthResponse(status=overall, components=components)
status_code = 503 if overall == "unhealthy" else 200
return JSONResponse(content=result.model_dump(), status_code=status_code)
return ORJSONResponse(content=result.model_dump(), status_code=status_code)