SPB Git

spb/forma-ka Public

Python 65.1% TypeScript 17.9% CSS 16.4% HTML 0.5%
2.3 KB · 63 lines python
Raw Blame History
1# -----------------------------------------------------------------------------2# Forma-Ka — Agrégateur de formations (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"[forma-ka] connecteur inconnu : {sid}", file=sys.stderr)26            continue27        t0 = time.time()28        print(f"[forma-ka] sync {sid} ...")29        try:30            formations = cls().fetch()31            finalized, dropped = [], 032            for fmt in formations:33                try:34                    finalized.append(fmt.finalize())35                except Exception:  # une fiche malformée 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"[forma-ka]   ⚠ ALERTE {sid} : {stats['alert']}")43            print(f"[forma-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"[forma-ka] prochaine synchronisation dans {interval_seconds}s")58        time.sleep(interval_seconds)596061if __name__ == "__main__":62    run(sys.argv[1:] or None)63