Aller au contenu principal

Couches & ports

Le code est organisé par fonctionnalité et, à l'intérieur d'une fonctionnalité, en trois niveaux :

  1. Adaptateurs HTTP (routers/) : analysent la requête, appellent le niveau inférieur, traduisent les erreurs en statuts HTTP.
  2. Logique applicative : cas d'usage (use_cases/) ou services fonctionnels (historical/, technical/, news/, valuation/, monitoring/, macro/).
  3. Adaptateurs vers l'extérieur : dépôts SQLAlchemy (database/), Redis (cache/), fournisseurs (financials/providers/, news/providers/, historical/providers.py).
┌──────────────── routers/ (FastAPI) ────────────────┐
│ parse request → call use case → map errors │
└──────────────────────────┬─────────────────────────┘
▼
┌──────── use_cases/ — depends on ports only ────────┐
│ GetFundamentals, GetDeepFundamentals, GetQuote… │
│ use_cases/ports.py: repository, cache, providers │
└──────────────────────────┬─────────────────────────┘
▼ implemented by
┌──── database/, cache/, financials/providers/ ──────┐
│ SQLAlchemy, Redis, HTTP │
└────────────────────────────────────────────────────┘

Dans quelle mesure chaque fonctionnalité le suit​

FonctionnalitéRouteurLogique applicativeDerrière des ports ?
Fondamentauxrouters/fundamentals.pyuse_cases/fundamentals.pyOui (use_cases/ports.py)
Fournisseurs spécialisésrouters/specialized.pyuse_cases/specialized.pyOui
Temps réelrouters/realtime.pyuse_cases/realtime.pyEn partie : le protocole WebSocket est dans le routeur
Indicateurs techniquesrouters/technical.pytechnical/indicator_service.pyOui (technical/contracts.py)
Surveillancerouters/monitoring.pymonitoring/En partie : le canary et la couche de validation utilisent monitoring/ports.py ; les requêtes de lecture des routes sont écrites dans le routeur
Historique et EODrouters/historical.py, routers/assets.pyhistorical/ingestion_service.py, database/query.pyNon
Valorisationrouters/valuation.pyvaluation/dcf_service.pyNon
Actualitésrouters/news.pynews/news_service.pyNon
Macro, exploitationrouters/macro.py, routers/admin.pymacro/, database/maintenance.py, cache/Non

La couche de cas d'usage est le modèle cible ; les autres fonctionnalités appellent directement leurs services.

Règles garanties par des tests​

  • technical/ n'importe ni FastAPI, ni SQLAlchemy, ni Redis, ni les modèles ORM ; monitoring/ n'importe ni SQLAlchemy ni les modèles ORM (tests/test_exception_boundaries.py).
  • Le code bloquant (sessions SQLAlchemy, pandas, yfinance) est atteint via concurrency.run_sync() depuis le code asynchrone (tests/test_async_boundary.py) : voir Concurrence.
  • Les routeurs traduisent les erreurs applicatives avec routers/errors.py.

Correspondance des erreurs​

Erreur applicative (use_cases/errors.py)Statut HTTP
InvalidInput400 Bad Request
ResourceNotFound404 Not Found
DependencyUnavailable503 Service Unavailable
UpstreamFailure500 Internal Server Error

Les indicateurs techniques ont leurs propres erreurs : indicateur inconnu 400, aucun prix 404, trop peu de barres 422.