Thermograph monorepo: graded-climate API + SSR frontend + infra, domain-specific containerized deploys
cache.js contained a JavaScript clone of backend/grid.py's snapping math (its own comment said so) to compute the 8 surrounding cells and fire 8 staggered prefetch requests — grid geometry had two homes, one per language, plus a client-side guess at Nominatim pacing. The server now owns it: grid.neighbors(cell) steps one cell width from the center and re-snaps (adjacent rows have different longitude steps; poles and the antimeridian handled by snap), and /api/v2/cell grew a neighbors=1 flag that enqueues those cells for a single background worker. The warm-only guarantee matches prefetch=1 — a cell with no cached archive is skipped, so no weather-API quota is ever spent — and reverse_geocode's own lock paces the at-most-one Nominatim call per never-labeled cell. Re-enqueues are TTL-deduped; the worker starts from the lifespan hook, so tests and offline importers never spawn it. The client now sends its one conditional bundle request with neighbors=1 (a warm spot costs an empty 304) instead of skipping the bundle and firing 8 extra requests; the grid-math clone and the now-unused hasFreshCache are deleted. Tests (114): grid.neighbors mid-latitude/pole/antimeridian, the neighbors=1 enqueue + TTL dedupe, _warm_cell materializing the history-derived store rows, and the never-fetch-upstream guarantee. Verified with the headless-Chromium smoke across all five pages. |
||
|---|---|---|
| tests | ||
| app.py | ||
| audit.py | ||
| climate.py | ||
| grading.py | ||
| grid.py | ||
| migrate.py | ||
| places.py | ||
| requirements-dev.txt | ||
| requirements.txt | ||
| store.py | ||
| views.py | ||