From 91389b9a3fc48fa0dce0b121b57a036597b79ae4 Mon Sep 17 00:00:00 2001 From: rene Date: Sat, 25 Apr 2026 22:00:26 +0200 Subject: [PATCH] =?UTF-8?q?Fix:=20Overpass-Fallback=20auf=20kumi.systems?= =?UTF-8?q?=20=E2=80=94=20overpass-api.de=20gibt=20406=20zur=C3=BCck?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit overpass-api.de und lz4.overpass-api.de blockieren die Server-IP mit 406. OVERPASS_URLS-Liste mit Fallback: kumi → lz4 → overpass-api.de. _fetch_overpass probiert jede Instanz, springt bei 4xx-Fehler zur nächsten. --- backend/routes/osm.py | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/backend/routes/osm.py b/backend/routes/osm.py index d462313..b1779dd 100644 --- a/backend/routes/osm.py +++ b/backend/routes/osm.py @@ -16,9 +16,13 @@ from auth import get_current_user, get_current_user_optional as get_optional_use logger = logging.getLogger(__name__) router = APIRouter() -CACHE_ZOOM = 12 -CACHE_DAYS = 14 -OVERPASS_URL = 'https://overpass-api.de/api/interpreter' +CACHE_ZOOM = 12 +CACHE_DAYS = 14 +OVERPASS_URLS = [ + 'https://overpass.kumi.systems/api/interpreter', + 'https://lz4.overpass-api.de/api/interpreter', + 'https://overpass-api.de/api/interpreter', +] # Globales Limit: max 2 gleichzeitige Overpass-Anfragen (Prewarm + User geteilt) _overpass_sem = asyncio.Semaphore(2) @@ -64,17 +68,24 @@ def _covering_tiles(south, west, north, east, zoom): # Overpass-Fetch + Cache # ------------------------------------------------------------------ async def _fetch_overpass(query): - for attempt in range(3): - async with _overpass_sem: - async with httpx.AsyncClient(timeout=40) as client: - r = await client.post(OVERPASS_URL, data={'data': query}) - if r.status_code != 429: - r.raise_for_status() + for url in OVERPASS_URLS: + for attempt in range(2): + try: + async with _overpass_sem: + async with httpx.AsyncClient(timeout=40) as client: + r = await client.post(url, data={'data': query}) + if r.status_code == 200: return r.json().get('elements', []) - logger.warning(f"Overpass 429 (Versuch {attempt + 1}/3)") - # Semaphore freigeben, dann warten - await asyncio.sleep(45 * (attempt + 1)) - raise Exception("Overpass 429 nach 3 Versuchen") + if r.status_code == 429: + logger.warning(f"Overpass 429 {url} (Versuch {attempt + 1}/2)") + await asyncio.sleep(30 * (attempt + 1)) + continue # gleiche URL nochmal + logger.warning(f"Overpass {r.status_code} {url} — nächste Instanz") + break # nächste URL + except Exception as exc: + logger.warning(f"Overpass Verbindungsfehler {url}: {exc}") + break # nächste URL + raise Exception("Alle Overpass-Instanzen fehlgeschlagen") def _stale_tiles(poi_type, tiles): stale = []