stats: paramètre syncs_since_h pour la fenêtre de synchronisations
GET /api/stats?syncs_since_h=<heures> retourne toutes les entrées de sync_log de la fenêtre (ts >= now - h*3600, ORDER BY ts DESC, LIMIT 4000) au lieu des 20 dernières seulement. Si moins de 20 entrées correspondent, repli sur les 20 dernières toutes époques confondues ; sans le paramètre, comportement historique inchangé. Corrige les fausses alertes « stale » du moniteur central api-ka : avec 109 sources et ~140 syncs/6 h, la fenêtre de 20 entrées polée aux 2 h ne montrait qu\une fraction des sources (realtor_ag_ca notamment, pourtant en succès à chaque cycle, ~2 145 fiches). Diagnostic connexe (aucun code à changer) : niddamour synchronise correctement — l\inventaire source.immo de l\agence ne contient que des locations (14 AVAILABLE à louer, 6 SOLD), zéro propriété à vendre, donc found=0 est légitime. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 changed file +15 −3
modified
immoka/web.py
+15 −3
@@ -361,7 +361,7 @@ def agencies(): | ||
| 361 | 361 | |
| 362 | 362 | |
| 363 | 363 | @app.get("/api/stats") |
| 364 | −def stats(): | |
| 364 | +def stats(syncs_since_h: float | None = None): | |
| 365 | 365 | con = db.connect() |
| 366 | 366 | row = con.execute( |
| 367 | 367 | """SELECT COUNT(*) total, |
@@ -371,8 +371,20 @@ def stats(): | ||
| 371 | 371 | MIN(price) min_price, |
| 372 | 372 | MAX(price) max_price |
| 373 | 373 | FROM listings WHERE active=1""" + DEDUP_CLAUSE).fetchone() |
| 374 | − log = [dict(r) for r in con.execute( | |
| 375 | − "SELECT * FROM sync_log ORDER BY ts DESC LIMIT 20")] | |
| 374 | + # Fenêtre de synchronisations pour la supervision (moniteur central api-ka) : | |
| 375 | + # sans paramètre, comportement historique (20 dernières entrées) ; avec | |
| 376 | + # ?syncs_since_h=<heures>, toutes les entrées de la fenêtre (borne 4000) — | |
| 377 | + # évite les fausses alertes « stale » quand 100+ sources synchronisent | |
| 378 | + # plus de 20 fois entre deux sondages. | |
| 379 | + log: list[dict] = [] | |
| 380 | + if syncs_since_h is not None: | |
| 381 | + cutoff = time.time() - syncs_since_h * 3600 | |
| 382 | + log = [dict(r) for r in con.execute( | |
| 383 | + "SELECT * FROM sync_log WHERE ts >= ?" | |
| 384 | + " ORDER BY ts DESC LIMIT 4000", (cutoff,))] | |
| 385 | + if len(log) < 20: | |
| 386 | + log = [dict(r) for r in con.execute( | |
| 387 | + "SELECT * FROM sync_log ORDER BY ts DESC LIMIT 20")] | |
| 376 | 388 | |
| 377 | 389 | # --- écart prix demandé vs estimation Vrai-Prix, par bannière ----------- |
| 378 | 390 | registry = json.loads(SOURCES_PATH.read_text(encoding="utf-8"))["sources"] |
| 379 | 391 | |