fix(feeds): 3 warnings externes

3 fixes pour reduire le bruit de logs des sources publiques :

wikimedia.py : ajoute User-Agent descriptif. WMF EventStreams
refuse l'UA httpx par defaut avec 403 Forbidden. Le 1.0+URL
descriptif est obligatoire pour le rate-limiting et les abuse
reports.

netzfrequenz.py : backoff exponentiel cap a 5 min sur les ws
disconnect. La source (mainsfrequenz.de) est NXDOMAIN depuis
mai 2026 ; on logguait toutes les 3 s soit ~28 800/jour. Avec
backoff x1.6 et log uniquement attempt==1 ou attempt%10, on
descend a ~30 log/jour.

config.data-only.toml : opensky poll_seconds 20 -> 60. L'API
anonyme est credit-based (10 req/min budget). 60s reste
raisonnable pour le viz tout en restaurant le credit.
This commit is contained in:
L'électron rare
2026-05-13 20:49:23 +02:00
parent 50343be6ec
commit bd3dd89511
3 changed files with 24 additions and 8 deletions
+4 -3
View File
@@ -65,9 +65,10 @@ ws_url = "wss://ws1.blitzortung.org:443/"
[feeds.opensky]
enabled = true
url = "https://opensky-network.org/api/states/all"
# API anonyme limitee a 1 req/15s. On laisse 20s de marge pour eviter
# les 429 sous drift d'horloge.
poll_seconds = 20
# API anonyme : 10 req / 1 min credit-based. On reste a 60s pour ne
# jamais epuiser le credit en cas de fork de process / restart rapide.
# Les 429 vus en 2026-05 etaient dus au poll 15s/20s precedent.
poll_seconds = 60
bbox = [45.5, 4.6, 46.0, 5.2]
# -- Pouls numérique -------------------------------------------------------
+13 -2
View File
@@ -22,10 +22,17 @@ async def run(ctx) -> None:
url = cfg["ws_url"]
time_dev = 0.0 # dérive intégrée (secondes)
last_t = time.monotonic()
# Backoff exponentiel cap a 5 minutes pour ne pas spammer un host
# mort (mainsfrequenz.de NXDOMAIN depuis 2026-05). On log la
# premiere et chaque dixieme reconnect uniquement.
backoff = 3.0
attempt = 0
while True:
try:
async with websockets.connect(url, ping_interval=20) as ws:
LOG.info("connected %s", url)
backoff = 3.0 # reset on success
attempt = 0
async for msg in ws:
text = msg if isinstance(msg, str) else msg.decode("utf-8", "ignore")
m = _RE_F.search(text)
@@ -45,5 +52,9 @@ async def run(ctx) -> None:
ctx.send("dev", delta)
ctx.send("time_dev", time_dev)
except Exception as e: # noqa: BLE001
LOG.warning("ws disconnected: %s — reconnecting", e)
await asyncio.sleep(3.0)
attempt += 1
if attempt == 1 or attempt % 10 == 0:
LOG.warning("ws disconnected (attempt %d, backoff %ds): %s",
attempt, int(backoff), e)
await asyncio.sleep(backoff)
backoff = min(backoff * 1.6, 300.0)
+7 -3
View File
@@ -27,12 +27,16 @@ async def run(ctx) -> None:
cfg = ctx.cfg
sample = float(cfg.get("sample_rate", 0.05)) # emit 5% des edits
window = float(cfg.get("rate_window_s", 5.0))
# WMF EventStreams refuse l'User-Agent par defaut httpx (403). Il
# faut une string descriptive + URL/email pour les abuse reports.
headers = {
"Accept": "text/event-stream",
"User-Agent": "av-live-data-feeds/1.0 (https://github.com/electron-rare/AV-Live)",
}
while True:
try:
async with httpx.AsyncClient(timeout=None) as cli:
async with cli.stream("GET", URL,
headers={"Accept": "text/event-stream"}
) as r:
async with cli.stream("GET", URL, headers=headers) as r:
r.raise_for_status()
bucket = 0
bucket_start = time.monotonic()