feat(api): GET /api/stats HUD counters (counts only, never 500) #42

Merged
sirius merged 1 commit from osint-dashboard/t_75d2037f-osint-get-api-stats-hud-counters into master 2026-08-31 22:12:55 -04:00
Owner

Summary

Adds GET /api/stats — a cheap counts-only endpoint (~100 B–2 KB) for the layer rail, so the HUD can poll counters without pulling megabytes of GeoJSON.

Returns:

{
  "aircraft": 0, "vessels": 0, "trains": 0, "cameras": 0,
  "fires": 0, "quakes": 0, "alerts": 0,
  "timestamp": "ISO8601Z"
}

How it works

  • In-memory last-known (O(1), no upstream fan-out on GET): aircraft and vessels from the existing aircraft_last_known / vessel_last_known dicts; trains and alerts from new last-known counters (train_count, nws_alert_count) that the Amtraker and NWS fetchers already update on their normal cadence.
  • Cheap SQL counts: cameras, fires (FIRMS table), and quakes (events where source_type='earthquake') via SELECT count(*).
  • Never 500: a down DB or missing table degrades those three counters to 0; the rail still renders.
  • Cached ~20 s in-process (Cache-Control: max-age=15), GZip already on the app.

Tests

tests/test_api_stats.py — 6 tests: 200 + all keys present, all counters are ints, timestamp is ISO8601-Z, payload < 2 KB, last-known counters reflected, and DB failure degrades to zero.

Out of scope

Leaflet rail wiring, new ingest, CelesTrak, camera parsers.

## Summary Adds `GET /api/stats` — a cheap counts-only endpoint (~100 B–2 KB) for the layer rail, so the HUD can poll counters without pulling megabytes of GeoJSON. Returns: ```json { "aircraft": 0, "vessels": 0, "trains": 0, "cameras": 0, "fires": 0, "quakes": 0, "alerts": 0, "timestamp": "ISO8601Z" } ``` ## How it works - **In-memory last-known** (O(1), no upstream fan-out on GET): `aircraft` and `vessels` from the existing `aircraft_last_known` / `vessel_last_known` dicts; `trains` and `alerts` from new last-known counters (`train_count`, `nws_alert_count`) that the Amtraker and NWS fetchers already update on their normal cadence. - **Cheap SQL counts**: `cameras`, `fires` (FIRMS table), and `quakes` (`events` where `source_type='earthquake'`) via `SELECT count(*)`. - **Never 500**: a down DB or missing table degrades those three counters to `0`; the rail still renders. - **Cached ~20 s** in-process (`Cache-Control: max-age=15`), GZip already on the app. ## Tests `tests/test_api_stats.py` — 6 tests: 200 + all keys present, all counters are ints, timestamp is ISO8601-Z, payload < 2 KB, last-known counters reflected, and DB failure degrades to zero. ## Out of scope Leaflet rail wiring, new ingest, CelesTrak, camera parsers.
sirius added 1 commit 2026-08-31 21:40:59 -04:00
sirius merged commit 240b9e70b3 into master 2026-08-31 22:12:55 -04:00
Sign in to join this conversation.
No reviewers
No labels
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: sirius/osint-dashboard#42
No description provided.