feat(parcels): §22 forecast in analyze endpoint — horizon+enqueue+GET (Step 3b-ii) #1069

Merged
bot-backend merged 1 commit from feat/forecast-endpoint-horizon-enqueue into main 2026-06-05 04:23:28 +00:00
Collaborator

What — Step 3b-ii (FINAL): §22 forecast reaches the analyze API

Completes EPIC 17 backend wiring. The 3b-i Celery task is live-validated (worker computes §22 in ~45s → persists schema_version="1.0" run). This wires it to the endpoint.

  • horizon query param on POST /{cad}/analyze — {6,12,18} (#995), default 12; invalid → 422 before any DB/compute (pre-flight guard).
  • Best-effort enqueue forecast_site_finder_report.delay(cad, horizon, created_by) after the existing persist — lazy import (no api↔workers cycle), try/except: Celery/Redis down → forecast.status="unavailable", analyze still 200 (never blocks/500s). Adds additive result_payload["forecast"] = {status: pending|unavailable, horizon}.
  • GET /{cad}/forecast (read-only): latest schema_version="1.0" run → 200 {status:ready, run_id, created_at, report} (the §22 dict) else 202 {status:pending}; graceful on DB error (202, never 500). Mirrors fetch-status RBAC/style.

Flow

POST /analyze?horizon=12 → site-analysis returns immediately (forecast.status=pending) + enqueues → worker runs §22 (~45-180s) → persists "1.0" → client polls GET /{cad}/forecast (202→200 with report.schema_version="1.0").

Quality

  • code-review APPROVE — analyze can't be broken/blocked/500'd by the enqueue + stays additive (verified risks etc. unchanged); horizon 422 before side-effects (.delay not called); GET reads "1.0" not "analyze-1.0", degrades to 202 not 500; enqueue arg-order correct; no import cycle; no new auth hole. 96 api tests pass; ruff/psycopg clean.
  • Minor (noted, non-blocking): GET swallows all exceptions → a persistent DB outage reads as "pending" (intended advisory posture; logger.warning(exc_info=True) mitigates — Glitchtip should watch it).

Additive only — existing analyze keys unchanged. Refs #995 #992 #961.

## What — Step 3b-ii (FINAL): §22 forecast reaches the analyze API Completes EPIC 17 backend wiring. The 3b-i Celery task is live-validated (worker computes §22 in ~45s → persists schema_version="1.0" run). This wires it to the endpoint. - **`horizon` query param** on `POST /{cad}/analyze` — {6,12,18} (#995), default 12; invalid → 422 **before any DB/compute** (pre-flight guard). - **Best-effort enqueue** `forecast_site_finder_report.delay(cad, horizon, created_by)` after the existing persist — lazy import (no api↔workers cycle), try/except: Celery/Redis down → `forecast.status="unavailable"`, analyze still 200 (never blocks/500s). Adds **additive** `result_payload["forecast"] = {status: pending|unavailable, horizon}`. - **`GET /{cad}/forecast`** (read-only): latest `schema_version="1.0"` run → **200** `{status:ready, run_id, created_at, report}` (the §22 dict) else **202** `{status:pending}`; graceful on DB error (202, never 500). Mirrors fetch-status RBAC/style. ## Flow `POST /analyze?horizon=12` → site-analysis returns immediately (`forecast.status=pending`) + enqueues → worker runs §22 (~45-180s) → persists "1.0" → client polls `GET /{cad}/forecast` (202→200 with `report.schema_version="1.0"`). ## Quality - **code-review APPROVE** — analyze can't be broken/blocked/500'd by the enqueue + stays additive (verified `risks` etc. unchanged); horizon 422 before side-effects (`.delay` not called); GET reads "1.0" not "analyze-1.0", degrades to 202 not 500; enqueue arg-order correct; no import cycle; no new auth hole. 96 api tests pass; ruff/psycopg clean. - Minor (noted, non-blocking): GET swallows all exceptions → a persistent DB outage reads as "pending" (intended advisory posture; `logger.warning(exc_info=True)` mitigates — Glitchtip should watch it). Additive only — existing analyze keys unchanged. Refs #995 #992 #961.
bot-backend added 1 commit 2026-06-05 04:23:25 +00:00
feat(parcels): wire §22 forecast into analyze endpoint (3b-ii, #995)
All checks were successful
Deploy / changes (push) Successful in 5s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 1m30s
Deploy / build-worker (push) Successful in 2m50s
Deploy / deploy (push) Successful in 1m14s
19584e0249
Final forecast wiring — §22 reaches the API.

- horizon query param on POST /{cad}/analyze ({6,12,18}, default 12; 422 before any
  DB/compute work otherwise).
- best-effort fire-and-forget forecast_site_finder_report.delay(cad, horizon,
  created_by) after persist (lazy import, no api↔workers cycle); Celery/Redis down →
  forecast.status='unavailable', analyze still 200 (never blocks/500s). Adds additive
  result_payload['forecast'] = {status: pending|unavailable, horizon}.
- new read-only GET /{cad}/forecast: latest schema_version='1.0' run → 200
  {status:ready, run_id, created_at, report} else 202 {status:pending}; graceful on DB
  error (202, never 500). Mirrors fetch-status RBAC/style.

Additive only — existing analyze response keys unchanged. code-review APPROVE
(analyze uncrashable + additive; 422 pre-flight; GET reads '1.0' not 'analyze-1.0').
96 api tests pass; ruff clean. Refs #995 #992 #961.
bot-backend merged commit 19584e0249 into main 2026-06-05 04:23:28 +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#1069
No description provided.