spb/food-ka Public
Food-Ka — agrégateur de produits d'épicerie du Québec — www.food-ka.com
Python 57.7%
TypeScript 24.9%
CSS 16.7%
HTML 0.6%
1# -----------------------------------------------------------------------------2# Food-Ka — Agrégateur de produits d'épicerie (province de Québec)3# Auteur : Simon-Pierre Boucher — contact@spboucher.ai4# ingest.py : pipeline d'ingestion — exécute les connecteurs et synchronise5# la base (ajouts / mises à jour / retraits) = contenu toujours à jour6# -----------------------------------------------------------------------------7from __future__ import annotations89import sys10import time11import traceback1213from . import db14from .connectors import CONNECTORS151617def run(sources: list[str] | None = None) -> list[dict]:18 """Exécute l'ingestion pour toutes les sources (ou celles demandées)."""19 con = db.connect()20 results = []21 targets = sources or list(CONNECTORS.keys())22 for sid in targets:23 cls = CONNECTORS.get(sid)24 if cls is None:25 print(f"[food-ka] connecteur inconnu : {sid}", file=sys.stderr)26 continue27 t0 = time.time()28 print(f"[food-ka] sync {sid} ...")29 try:30 products = cls().fetch()31 finalized, dropped = [], 032 for prod in products:33 try:34 finalized.append(prod.finalize())35 except Exception: # un produit malformé ne bloque pas la source36 dropped += 137 stats = db.sync_source(con, sid, finalized)38 stats["seconds"] = round(time.time() - t0, 1)39 if dropped:40 stats["dropped"] = dropped41 if stats.get("alert"):42 print(f"[food-ka] ⚠ ALERTE {sid} : {stats['alert']}")43 print(f"[food-ka] {stats}")44 results.append(stats)45 except Exception as exc: # robustesse : une source ne bloque pas les autres46 db.log_failure(con, sid, f"{exc}")47 traceback.print_exc()48 results.append({"source": sid, "error": str(exc)})49 con.close()50 return results515253def watch(interval_seconds: int = 3600) -> None:54 """Boucle de rafraîchissement périodique (pseudo-webhook par sondage)."""55 while True:56 run()57 print(f"[food-ka] prochaine synchronisation dans {interval_seconds}s")58 time.sleep(interval_seconds)596061if __name__ == "__main__":62 run(sys.argv[1:] or None)63