diff --git a/backend/routes/osm.py b/backend/routes/osm.py index 7c1cd58..2c7375b 100644 --- a/backend/routes/osm.py +++ b/backend/routes/osm.py @@ -24,8 +24,11 @@ OVERPASS_URLS = [ 'https://overpass-api.de/api/interpreter', ] -# Globales Limit: max 2 gleichzeitige Overpass-Anfragen (Prewarm + User geteilt) -_overpass_sem = asyncio.Semaphore(2) +# Max 1 gleichzeitige Overpass-Anfrage + 2s Mindestabstand (Fair Use) +_overpass_sem = asyncio.Semaphore(1) +_overpass_last_req = 0.0 +_OVERPASS_MIN_DELAY = 2.0 # Sekunden zwischen Anfragen +_OVERPASS_UA = 'BanYaro/1.0 (https://banyaro.app; dog-walking PWA; contact: mail@motocamp.de)' OSM_QUERIES = { 'waste_basket': '[out:json][timeout:20];node["amenity"="waste_basket"]({bbox});out;', @@ -68,12 +71,22 @@ def _covering_tiles(south, west, north, east, zoom): # Overpass-Fetch + Cache # ------------------------------------------------------------------ async def _fetch_overpass(query): + global _overpass_last_req for url in OVERPASS_URLS: for attempt in range(2): try: async with _overpass_sem: - async with httpx.AsyncClient(timeout=40) as client: + # Fair-Use: Mindestabstand zwischen Anfragen einhalten + import time + wait = _OVERPASS_MIN_DELAY - (time.monotonic() - _overpass_last_req) + if wait > 0: + await asyncio.sleep(wait) + async with httpx.AsyncClient( + timeout=40, + headers={'User-Agent': _OVERPASS_UA}, + ) as client: r = await client.post(url, data={'data': query}) + _overpass_last_req = time.monotonic() if r.status_code == 200: return r.json().get('elements', []) if r.status_code == 429: