trails/apps/planner
Ullrich Schäfer 963902514b
Failover across multiple Overpass upstreams
Public Overpass instances go bad without warning — we just lived
through a day where overpass.private.coffee (our single upstream)
returned 504s after 60s while lz4.overpass-api.de served the same
query in 0.6s. Survive that by trying a list of upstreams in order
until one responds usefully.

Server changes:
- OVERPASS_URLS env — comma-separated list, tried in order. Falls
  back to OVERPASS_URL for backward compat, then to a built-in
  default pair (lz4.overpass-api.de, overpass-api.de).
- Per-upstream timeout of 10s via AbortSignal.timeout, so a saturated
  instance fails over in seconds, not minutes.
- Client abort propagation via AbortSignal.any — if the browser
  cancels (e.g. user panned the map), the in-flight upstream fetch is
  aborted too. Stops wasting upstream capacity on requests nobody
  wants.
- Rate-limited-body detection (Overpass returns 200 with a
  `rate_limited` marker when throttling) triggers failover.
- Per-upstream labels on overpass_upstream_requests_total and
  overpass_upstream_duration_seconds so the dashboard can break out
  health + latency by instance. Histogram buckets extended to 30s.

Compose: OVERPASS_URLS passthrough with the default pair hard-wired,
overridable via SOPS.

Tests: 8 cases covering the new fetchWithFailover helper — happy
path, 5xx failover, rate_limited failover, network error failover,
timeout tagging, all-upstreams-fail, client abort stops the loop,
per-attempt latency observation.

Follow-ups left out of scope:
- Client-side debounce (UI concern).
- Moving `.observe()` after body read for accuracy in measurement.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 07:36:10 +02:00
..
app Failover across multiple Overpass upstreams 2026-04-21 07:36:10 +02:00
public Add favicons, apple-touch-icons, and Chrome DevTools JSON 2026-03-29 10:35:03 +02:00
Dockerfile Stop Sentry on logout; fix E2E + Dockerfile for merged consolidation 2026-04-18 00:40:36 +02:00
package.json Bump the production group with 10 updates 2026-04-19 21:40:33 +02:00
react-router.config.ts Complete monorepo toolchain setup (tasks 1.1-1.7) 2026-03-22 12:12:57 +01:00
server.ts Consolidate Sentry config into shared package; fix inconsistencies 2026-04-18 00:30:09 +02:00
tsconfig.json Fix planner production server + use .ts extensions everywhere 2026-03-25 01:41:33 +01:00
vite.config.ts Fix Sentry build: disable telemetry, fix release version passing 2026-03-27 18:18:00 +01:00
vitest.config.ts Failover across multiple Overpass upstreams 2026-04-21 07:36:10 +02:00