Kazeia-central/kazeia_central/core/context.py

58 lines
1.9 KiB
Python

"""Contexte applicatif injecté dans les routers de features.
Patron évolutif : chaque feature expose `make_router(ctx) -> APIRouter` et reçoit ce
contexte (adb, store, bridge, autosync, identité opérateur) + les helpers transverses
(`guard` = mapping exceptions→HTTP, `now_ms`, `client`). Ajouter une feature = créer son
router et l'enregistrer dans `app.create_app` — sans toucher au reste.
"""
from __future__ import annotations
import time
from dataclasses import dataclass
from typing import Any, Callable
from fastapi import HTTPException
from .adb import Adb, AdbError
from .provider import ProviderClient
from .store import Store, StoreLocked
VERSION = "0.1.0"
@dataclass
class Ctx:
adb: Adb
store: Store
bridge: Any # VoiceBridge (feature voices) — typé Any pour découpler core
autosync: Any # VoiceAutoSync
operator: str
@staticmethod
def now_ms() -> int:
return int(time.time() * 1000)
def client(self, serial: str) -> ProviderClient:
return ProviderClient(self.adb, serial)
def guard(self, fn: Callable):
"""Exécute `fn`, mappe les exceptions de domaine en HTTP. Les erreurs de
feature peuvent porter un attribut `http_status` (ex. VoiceWorkerError=503)
pour rester découplées du core."""
try:
return fn()
except HTTPException:
raise
except AdbError as e:
raise HTTPException(502, str(e)) from e
except StoreLocked as e:
raise HTTPException(423, str(e)) from e
except IndexError as e: # endpoint a renvoyé 0 ligne
raise HTTPException(404, "aucune donnée") from e
except Exception as e:
code = getattr(type(e), "http_status", None)
if code:
raise HTTPException(code, str(e)) from e
raise