App 2.39.1, server 2.8.0: map roads from OpenFreeMap, on demand

The public Overpass answered 429/502 and needs ~40 s a tile while the
car gives up after 8 s, so the server cancelled its queries and the
car's retries added load. Now the server fetches only the tiles a car
asks for, as OpenStreetMap vector tiles from OpenFreeMap (MAP_TILES_URL),
decodes the transportation layer with a small reader of its own, and
keeps each tile 30 days on a volume (MAP_CACHE_DIR). A fetch finishes
even after the car has stopped waiting; the car hears 503 with
Retry-After and gets the tile on its next try.

App: OpenFreeMap/OpenMapTiles attribution on the map, retry after 15 s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
This commit is contained in:
2026-10-26 23:54:30 +01:00
co-authored by Claude Opus 5.5
parent d9c7c5ea9a
commit 6be2ba5193
17 changed files with 891 additions and 332 deletions
+20
View File
@@ -138,6 +138,26 @@ tyre pressures, GPS (lat, lon, elevation, heading) and the is_* flags. It does *
confirmed car facts, app structure, UI conventions, build/test/ship, documents. It replaces
upstream's EVABRPUploader text. The test emulator is now in the flake: `nix run .#car-emulator`
(Android 9 AOSP at 1920×720, 160 dpi; the car build installs as the system user — checked).
- 2026-10-26 — App 2.39.1 and server 2.8.0: **the map's roads come from OpenFreeMap, on
demand.** In the car, server 2.7.0 logged `overpass answered 502`, `overpass could not be
reached`, and the owner saw 429s: the public Overpass limits per IP, and a tile takes it ~40 s
while the car gives up after 8 s (`ServerHttp.TIMEOUT_MS`) — the server then cancelled the
query, threw the work away, and the car's retries added to the load. Owner's choice: fetch
only the tiles the car asks for (a self-hosted Overpass would need a whole region imported).
Server: the zoom-14 OpenStreetMap vector tile (OpenMapTiles schema) from the TileJSON at
`MAP_TILES_URL` (default OpenFreeMap, free, no key, no limits; its template re-read every 6 h,
https only), decoded by our own minimal protobuf/MVT reader (`mvt.go`, the `transportation`
layer; classes motorway/trunk, primary/secondary, tertiary, minor), simplified as before. A
fetch runs to its end without the car (requests wait ≤ 6 s, then 503 with `Retry-After: 10`),
at most two at once, one per tile; tiles kept 30 days in `MAP_CACHE_DIR` (a 1 Gi volume
`mg4-server-maps`, pod `fsGroup` 65532) and the last 300 in memory; `OVERPASS_URL` is gone.
Tests with an encoded vector tile and a fake tile host (classes, split lines, scaled extent,
malformed tiles, gzip from the host, fetched once and kept across a restart, a slow fetch
finished for the next try, failures not cached and no tile in the log, http template refused,
config). Real: the 9 Berlin tiles in 0.7 s (9–15 KB each). App 2.39.1: "OpenFreeMap ©
OpenMapTiles · © OpenStreetMap contributors" on the map, a tile the server did not have yet is
asked for again after 15 s (was a minute). Emulator with those tiles: same roads as before.
Not tried: the deployed server and the car.
- 2026-10-26 — Server 2.7.0 image pushed (`git.stinnesbeck.com/nils/mg4-server:2.7.0`, Go 1.27.3,
govulncheck clean) and pinned in `k8s/server.yaml` by digest
`sha256:e5da9452a9dbdfabe3340766cc51f18bb1418b2588ab534714550470abe1ce29` (checked with skopeo);