SPB Git forge

spb/api-ka

Public

API-KA — plateforme centrale : collecte quotidienne des 8 services KA, historisation append-only et API publique sur www.api-ka.com

48commits 1branches 0releases
5.9 MBsize
maindefault branch
19 days agolast push
Python 60.9% HTML 21% TypeScript 7.3% JavaScript 5.2% CSS 4.8% Shell 0.8%
2.6 KB · 80 lines python
Raw Blame History
1# ============================================2# Projet   : API-KA3# Fichier  : src/api/routes/health.py4# Node     : m3u96b5# Author   : Simon-Pierre Boucher6# Contact  : contact@spboucher.ai7# Date     : 2026-08-168# ============================================9"""Route /health : node (m3u96b), état de la base, dernière collecte par service."""1011from __future__ import annotations1213import socket14from typing import Any1516from fastapi import APIRouter, Depends17from sqlalchemy import func, select18from sqlalchemy.orm import Session1920from src.api.routes import envelope21from src.config import REQUIRED_NODE, SERVICES22from src.database.db import get_db, healthcheck23from src.database.models import CollectionRun, ConnectorHealth24from src.monitoring.connector_health import ALL_STATUSES2526router = APIRouter(tags=["health"])272829@router.get("/health")30def health(db: Session = Depends(get_db)) -> dict[str, Any]:31    """État complet de la plateforme : node, base de données, dernières collectes."""32    hostname = socket.gethostname()33    db_ok = healthcheck()3435    last_collections: dict[str, Any] = {}36    for service in SERVICES:37        last_run = (38            db.execute(39                select(CollectionRun)40                .where(41                    CollectionRun.service == service,42                    CollectionRun.status.in_(("success", "retried")),43                )44                .order_by(CollectionRun.finished_at.desc())45                .limit(1)46            )47            .scalars()48            .first()49        )50        last_collections[service] = (51            {52                "date_key": last_run.date_key.isoformat(),53                "status": last_run.status,54                "records_count": last_run.records_count,55                "finished_at": last_run.finished_at.isoformat(),56            }57            if last_run58            else None59        )6061    # Résumé de la supervision des connecteurs de l'écosystème (table62    # connector_health, alimentée toutes les 2 h par apika-scheduler).63    connectors = dict.fromkeys(ALL_STATUSES, 0)64    for status, count in db.execute(65        select(ConnectorHealth.status, func.count()).group_by(ConnectorHealth.status)66    ):67        if status in connectors:68            connectors[status] = count6970    data = {71        "status": "ok" if db_ok else "degraded",72        "node": hostname,73        "required_node": REQUIRED_NODE,74        "node_ok": hostname.split(".")[0].lower() == REQUIRED_NODE,75        "database": "ok" if db_ok else "error",76        "last_collections": last_collections,77        "connectors": connectors,78    }79    return envelope(data)80