Persist each successful POST /analyze into analysis_runs (migration 127): best-effort SAVEPOINT-wrapped INSERT in a thin analysis_runs repository, then explicit db.commit() (get_db has no commit-on-success; SAVEPOINT RELEASE alone does not persist — without the commit the row rolls back on request teardown, a silent no-op caught in code review). A persist failure never breaks the response or poisons the session. Result serialized via jsonable_encoder→ json.dumps (handles embedded Pydantic models/dates); confidence/status normalized to satisfy the 127 CHECK constraints (unknown→NULL/'complete'). Populate by-bbox last_analysis_date from v_analysis_runs_latest via a single batch query (no N+1), replacing the #307 placeholder. The read is best-effort wrapped too — a view-missing deploy window or future drift must not 500 the map (falls back to last_analysis_date=None). Additive only — analyze response shape unchanged. Tests: by-bbox suite patches latest_run_dates (mock-db returns same rows for any query) + new test asserts ISO last_analysis_date from a latest run. Analyze mock-suite unaffected (graceful side_effect overflow + best-effort persist absorb the extra INSERT). Incidental: ruff-format fixed one pre-existing f-string spacing (line ~2391) the format hook flags on touch. Closes #994. Refs #961. |
||
|---|---|---|
| .. | ||
| api | ||
| integration | ||
| scrapers | ||
| scripts | ||
| services | ||
| smoke | ||
| sql | ||
| workers | ||
| __init__.py | ||
| test_admin_weight_profiles.py | ||
| test_concepts_stub.py | ||
| test_gate_verdict.py | ||
| test_health.py | ||
| test_layout_signature.py | ||
| test_layout_tz_pdf.py | ||
| test_nspd_client.py | ||
| test_nspd_sync.py | ||
| test_ping.py | ||
| test_poi_score.py | ||
| test_quarter_dump_lookup.py | ||
| test_rbac.py | ||
| test_sentry_init.py | ||
| test_velocity.py | ||
| test_weight_profiles.py | ||