mirror of
https://github.com/koala73/worldmonitor.git
synced 2026-04-25 17:14:57 +02:00
* feat(supply-chain): Sprint E — scenario visual completion + service parity - E1: fetchSectorDependency exported from supply-chain service index - E2: PRO gate + all-renderer dispatch in MapContainer.activateScenario - E3: scenario summary banner in SupplyChainPanel (dismiss wired) - E4: "Simulate Closure" trigger button in expanded chokepoint cards - E5: affectedIso2s heat layer in DeckGLMap (GeoJsonLayer, red tint) - E6: SVG renderer setScenarioState (best-effort iso2 fill) - E7: Globe renderer scenario polygons via flushPolygons - E8: integration tests for scenario run/status endpoints * fix(supply-chain): address PR #2910 review findings (P1 + P2 + P3) - Wire setOnScenarioActivate + setOnDismissScenario in panel-layout.ts (todo #155) - Rename shadow variable t→tmpl in SCENARIO_TEMPLATES.find (todo #152) - Add statusResp.ok guard in scenario polling loop (todo #153) - Replace status.result! non-null assertion with shape guard (todo #154) - Add AbortController to prevent concurrent polling races (todo #162) - Add polygonStrokeColor scenario branch (transparent) in GlobeMap (todo #156) - Re-export SCENARIO_TEMPLATES via src/config/scenario-templates.ts (todo #157) - Cache affectedIso2Set in DeckGLMap.setScenarioState (todo #158) - Add scenario paths to PREMIUM_RPC_PATHS for auth injection (todo #160) - Show template name in scenario banner instead of raw ID (todo #163) * fix(supply-chain): address PR #2910 review findings - Add auth headers to scenario fetch calls in SupplyChainPanel - Reset button state on scenario dismiss - Poll status immediately on first iteration (no 2s delay) - Pre-compute scenario polygons in GlobeMap.setScenarioState - Use scenarioId for DeckGL updateTriggers precision * fix(supply-chain): wire panel instance to MapContainer, stop button click propagation - Call setSupplyChainPanel() in panel-layout.ts so scenario banner renders - Add stopPropagation() to Simulate Closure button to prevent card collapse
57 lines
2.1 KiB
Markdown
57 lines
2.1 KiB
Markdown
---
|
||
status: complete
|
||
priority: p1
|
||
issue_id: "153"
|
||
tags: [code-review, quality, supply-chain, reliability]
|
||
dependencies: []
|
||
---
|
||
|
||
# Missing `statusResp.ok` Guard in Scenario Polling Loop
|
||
|
||
## Problem Statement
|
||
In `SupplyChainPanel.ts:677`, the polling loop calls `statusResp.json()` without first checking `statusResp.ok`. A 429, 500, or network error causes `.json()` to throw or produce garbage, silently burning through all 30 iterations. The button ends up stuck on "Computing…" for 60 seconds before showing "Error — retry" with no useful signal.
|
||
|
||
## Findings
|
||
- **File:** `src/components/SupplyChainPanel.ts`, line 677
|
||
- **Code:**
|
||
```ts
|
||
const statusResp = await fetch(`/api/scenario/v1/status?jobId=${encodeURIComponent(jobId)}`);
|
||
const status = await statusResp.json() as { status: string; result?: ScenarioResult };
|
||
```
|
||
- No check on `statusResp.ok` before consuming body
|
||
- 30 × 2s = 60s of silent failure with no feedback to the user
|
||
|
||
## Proposed Solutions
|
||
|
||
### Option A: Guard before `.json()` (Recommended)
|
||
```ts
|
||
const statusResp = await fetch(`/api/scenario/v1/status?jobId=${encodeURIComponent(jobId)}`);
|
||
if (!statusResp.ok) throw new Error(`Status poll failed: ${statusResp.status}`);
|
||
const status = await statusResp.json() as { status: string; result?: ScenarioResult };
|
||
```
|
||
**Pros:** Fails fast on server error, exits loop immediately
|
||
**Cons:** None
|
||
**Effort:** Small | **Risk:** None
|
||
|
||
### Option B: Retry on non-fatal errors, throw on fatal
|
||
Skip 429/503, throw on 4xx. More complex, adds ~10 lines, probably not worth it for this use case.
|
||
**Effort:** Medium | **Risk:** Low
|
||
|
||
## Recommended Action
|
||
_Apply Option A — guard before `.json()`. One line._
|
||
|
||
## Technical Details
|
||
- **Affected files:** `src/components/SupplyChainPanel.ts`
|
||
- **Line:** 677
|
||
|
||
## Acceptance Criteria
|
||
- [ ] `statusResp.ok` checked before calling `.json()`
|
||
- [ ] Loop exits immediately (throws) on non-OK response
|
||
- [ ] Button shows "Error — retry" within one polling cycle on server error
|
||
|
||
## Work Log
|
||
- 2026-04-10: Identified by kieran-typescript-reviewer during PR #2910 review
|
||
|
||
## Resources
|
||
- PR: #2910
|