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
2.9 KiB
2.9 KiB
status, priority, issue_id, tags, dependencies
| status | priority | issue_id | tags | dependencies | ||||
|---|---|---|---|---|---|---|---|---|
| complete | p2 | 158 |
|
createScenarioHeatLayer Allocates New Set on Every buildLayers() Call
Problem Statement
DeckGLMap.createScenarioHeatLayer() constructs new Set(this.scenarioState.affectedIso2s) inside the method body. buildLayers() is called on every frame/render cycle by DeckGL when layers need to be rebuilt. The Set allocation is O(n) on the number of affected ISO-2 codes and runs inside the hot DeckGL render path.
Findings
- File:
src/components/DeckGLMap.ts - Code:
private createScenarioHeatLayer(): GeoJsonLayer | null { if (!this.scenarioState?.affectedIso2s?.length || !this.countriesGeoJsonData) return null; const affected = new Set(this.scenarioState.affectedIso2s); // ← allocated every call return new GeoJsonLayer({ ..., getFillColor: (feature) => { const code = ...; return affected.has(code) ? ... } }); } buildLayers()is called whenever deck viewport or layers change — potentially dozens of times per second during pan/zoom- The
Setcontents only change whensetScenarioState()is called (rare) - Identified by performance-oracle during PR #2910 review
Proposed Solutions
Option A: Cache the Set in setScenarioState() (Recommended)
private affectedIso2Set: Set<string> = new Set();
public setScenarioState(state: ScenarioVisualState | null): void {
this.scenarioState = state;
this.affectedIso2Set = new Set(state?.affectedIso2s ?? []);
this.rebuildLayers();
}
private createScenarioHeatLayer(): GeoJsonLayer | null {
if (!this.affectedIso2Set.size || !this.countriesGeoJsonData) return null;
return new GeoJsonLayer({ ..., getFillColor: (feature) => {
const code = feature.properties?.['ISO3166-1-Alpha-2'] as string | undefined;
return (code && this.affectedIso2Set.has(code) ? [220, 60, 40, 80] : [0, 0, 0, 0]) as [number,number,number,number];
}});
}
Pros: Set allocated once per state change (not per render), correct updateTriggers still invalidates DeckGL cache
Cons: Small memory overhead for the cached Set field
Effort: Small | Risk: Low
Option B: Keep as-is with a comment
Acceptable if buildLayers() is only called on state change. But DeckGL calls it more often.
Effort: None | Risk: High (performance regression on active globe interactions)
Recommended Action
Apply Option A — cache the Set in setScenarioState().
Technical Details
- Affected files:
src/components/DeckGLMap.ts - Add private
affectedIso2Set: Set<string> = new Set()field - Move Set construction to
setScenarioState()
Acceptance Criteria
createScenarioHeatLayerdoes not allocate a newSeton each callsetScenarioState()rebuilds the cached Setnpm run typecheckpasses
Work Log
- 2026-04-10: Identified by performance-oracle during PR #2910 review
Resources
- PR: #2910