feat(forecast): forecast Celery task + persist §22 «1.0» (Step 3b-i) #1068

Merged
bot-backend merged 1 commit from feat/forecast-celery-task-persist into main 2026-06-05 04:02:48 +00:00
Collaborator

What — Step 3b-i: forecast Celery task + persist §22 (no endpoint trigger yet)

The §22 orchestrator build_site_finder_report (3a, #1056) takes ~30-180s → can't run inline on the sync /analyze. This adds the background Celery task that runs it and persists the result as a schema_version="1.0" run.

  • repository.latest_run_for(db, cad_num, *, schema_version=None) — keyword-only param (default None = current v_analysis_runs_latest, backward-compat; sole existing caller unaffected). When given → base-table analysis_runs WHERE cad_num AND schema_version ORDER BY created_at DESC LIMIT 1 (index-served via #127), so the task fetches the latest analyze-1.0 site-analysis run even when newer 1.0 rows exist on top.
  • workers/tasks/forecast.py::forecast_site_finder_report(cad_num, horizon=12, created_by) — reads latest analyze-1.0 → build_site_finder_report(analyze=row.result, …)persist_analysis_run(result=report.as_dict(), schema_version="1.0", status, confidence, segment, params). Graceful: no base run / compute error → log + return None (worker not crashed). time_limit=900/soft=840. Registered in celery include.

Prod-confirmed input assumption

analyze-1.0 runs store the full analyze dict in result (competitors=20, district populated — verified on 66:41:0702048:27/Кировский, 66:41:0204016:10/Железнодорожный) → the orchestrator's analyze input read from the persisted run is valid.

Quality

  • code-review APPROVE — schema-read backward-compat + psycopg3-safe (CAST, no :x::type, index-served); task degrades gracefully (no worker crash) + persists "1.0" (contract verified against the real SiteFinderReport.as_dict()); status="done"→normalized→"complete" (CHECK-valid, no IntegrityError). Tests genuine (filtered-read returns analyze-1.0 over newer 1.0; happy/graceful paths).
  • 943 tests pass; ruff clean. Endpoint/orchestrator/§9.x untouched.

Inert until 3b-ii wires the /analyze?horizon= enqueue (next). Full live-chain prod ground-truth lands with 3b-ii (analyze→task→§22 row→fetch). Refs #994 #961.

## What — Step 3b-i: forecast Celery task + persist §22 (no endpoint trigger yet) The §22 orchestrator `build_site_finder_report` (3a, #1056) takes ~30-180s → can't run inline on the sync `/analyze`. This adds the **background Celery task** that runs it and persists the result as a `schema_version="1.0"` run. - **`repository.latest_run_for(db, cad_num, *, schema_version=None)`** — keyword-only param (default None = current `v_analysis_runs_latest`, backward-compat; sole existing caller unaffected). When given → base-table `analysis_runs WHERE cad_num AND schema_version ORDER BY created_at DESC LIMIT 1` (index-served via #127), so the task fetches the latest **analyze-1.0** site-analysis run even when newer 1.0 rows exist on top. - **`workers/tasks/forecast.py::forecast_site_finder_report(cad_num, horizon=12, created_by)`** — reads latest analyze-1.0 → `build_site_finder_report(analyze=row.result, …)` → `persist_analysis_run(result=report.as_dict(), schema_version="1.0", status, confidence, segment, params)`. Graceful: no base run / compute error → log + return None (worker not crashed). `time_limit=900/soft=840`. Registered in celery `include`. ## Prod-confirmed input assumption `analyze-1.0` runs store the **full** analyze dict in `result` (competitors=20, district populated — verified on 66:41:0702048:27/Кировский, 66:41:0204016:10/Железнодорожный) → the orchestrator's `analyze` input read from the persisted run is valid. ## Quality - **code-review APPROVE** — schema-read backward-compat + psycopg3-safe (CAST, no `:x::type`, index-served); task degrades gracefully (no worker crash) + persists "1.0" (contract verified against the real `SiteFinderReport.as_dict()`); `status="done"`→normalized→"complete" (CHECK-valid, no IntegrityError). Tests genuine (filtered-read returns analyze-1.0 over newer 1.0; happy/graceful paths). - 943 tests pass; ruff clean. Endpoint/orchestrator/§9.x untouched. **Inert until 3b-ii** wires the `/analyze?horizon=` enqueue (next). Full live-chain prod ground-truth lands with 3b-ii (analyze→task→§22 row→fetch). Refs #994 #961.
bot-backend added 1 commit 2026-06-05 04:02:46 +00:00
feat(forecast): forecast_site_finder_report Celery task + schema-filtered run read (3b-i)
All checks were successful
Deploy / changes (push) Successful in 6s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 1m21s
Deploy / build-worker (push) Successful in 2m39s
Deploy / deploy (push) Successful in 1m11s
c94810f3a7
build_site_finder_report (§22) takes ~30-180s → runs in a background Celery task,
not inline on the sync /analyze endpoint.

- repository: latest_run_for gains keyword-only schema_version (default None keeps
  v_analysis_runs_latest behavior, backward-compat); when given, reads base
  analysis_runs filtered by schema_version ORDER BY created_at DESC LIMIT 1 — fetches
  the latest analyze-1.0 site-analysis run even when newer 1.0 (§22) rows exist on top
  (index-served via 127's (cad_num, created_at DESC)).
- new workers/tasks/forecast.py::forecast_site_finder_report: reads latest analyze-1.0,
  runs the §22 orchestrator, persists SiteFinderReport.as_dict() as a 1.0 run via
  persist_analysis_run. Graceful: no base run / compute error → logger + return None
  (worker not crashed). time_limit=900/soft=840 (no global limit). Registered in include.

Prod-confirmed: analyze-1.0 result carries the full analyze dict (competitors+district)
→ orchestrator input valid. Endpoint trigger (3b-ii) + §9.x untouched. 943 tests pass;
code-review APPROVE (contracts verified vs real as_dict(); status done→complete normalized,
no IntegrityError). Refs #994 #961.
bot-backend merged commit c94810f3a7 into main 2026-06-05 04:02:48 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#1068
No description provided.