Ajoute test/ a la liste des prefixes de branches, deja utilise par la branche d'outillage frontend, et remplace le corps a trous du gabarit de repository par un exemple complet, que ruff format acceptait mal.
113 lines
4.3 KiB
Markdown
113 lines
4.3 KiB
Markdown
# Backend EnerVision
|
|
|
|
API FastAPI exposant les series temporelles energetiques.
|
|
|
|
| Element | Choix |
|
|
|-------------|--------------------------------------------|
|
|
| Python | 3.14 |
|
|
| Gestionnaire| uv (`uv.lock` fait foi) |
|
|
| Framework | FastAPI + Uvicorn |
|
|
| Persistance | SQLAlchemy 2 async + asyncpg + Alembic |
|
|
| Lint/format | ruff |
|
|
| Typage | mypy en mode strict |
|
|
| Tests | pytest + pytest-asyncio + httpx |
|
|
|
|
## Installation
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
uv sync --all-groups
|
|
```
|
|
|
|
`APP_SECRET_KEY` et `DATABASE_URL` n'ont pas de valeur par defaut : l'application refuse
|
|
de demarrer sans elles.
|
|
|
|
`DATABASE_URL` pointe sur `localhost:5433`, le port publie par le service `db` du
|
|
`docker-compose.yml` racine. Demarrer la base depuis la racine avec `make db-up`.
|
|
|
|
## Commandes
|
|
|
|
Depuis la racine du monorepo, via le `Makefile` : `make install`, `make dev`, `make lint`,
|
|
`make format`, `make typecheck`, `make test`, `make check`, `make docker-build`.
|
|
|
|
Directement depuis ce dossier :
|
|
|
|
```bash
|
|
uv run uvicorn app.main:create_app --factory --reload --port 8000
|
|
uv run ruff check . # lint
|
|
uv run ruff format . # format
|
|
uv run mypy app # typage strict
|
|
uv run pytest # tests + couverture
|
|
uv run pytest -m integration # tests exigeant une base joignable
|
|
```
|
|
|
|
Les conventions de tests, les gabarits et le detail des marqueurs sont dans
|
|
[`TESTING.md`](TESTING.md).
|
|
|
|
`pytest` ecarte par defaut les tests marques `integration`, pour que `make check` reste
|
|
jouable sans Docker. Ces tests visent la base `enervision_test`, creee par
|
|
`db/init/110-test-database.sql` au premier demarrage du conteneur.
|
|
|
|
L'application est exposee par une factory (`create_app`) et non par un objet module :
|
|
aucune configuration n'est lue a l'import, ce qui rend les tests et les migrations
|
|
independants de l'environnement.
|
|
|
|
## Structure
|
|
|
|
```
|
|
app/
|
|
├── api/
|
|
│ ├── deps.py Dependances FastAPI partagees (session, settings)
|
|
│ └── v1/
|
|
│ ├── router.py Agregation des routes de la version 1
|
|
│ └── endpoints/ Un module par ressource exposee
|
|
├── core/
|
|
│ ├── config.py Settings Pydantic, source unique de configuration
|
|
│ └── logging.py Journalisation console en local, JSON en production
|
|
├── db/
|
|
│ ├── base.py Base declarative SQLAlchemy
|
|
│ └── session.py Engine et sessions asynchrones
|
|
├── models/ Modeles SQLAlchemy
|
|
├── schemas/ Modeles Pydantic d'entree et de sortie
|
|
├── repositories/ Acces aux donnees, une classe par agregat
|
|
├── services/ Regles metier, orchestrent les repositories
|
|
└── main.py Factory applicative
|
|
tests/ Miroir de app/
|
|
alembic/ Migrations du schema applicatif
|
|
```
|
|
|
|
Le sens de dependance est unique : `endpoints` vers `services` vers `repositories` vers
|
|
`models`. Un endpoint ne touche jamais une session directement.
|
|
|
|
## Routes
|
|
|
|
| Route | Role |
|
|
|------------------------|-------------------------------------------------|
|
|
| `/api/v1/health/live` | Sonde de vivacite, aucune dependance externe |
|
|
| `/api/v1/health/ready` | Sonde de disponibilite, verifie la base et TimescaleDB |
|
|
| `/metrics` | Metriques au format Prometheus |
|
|
| `/docs`, `/openapi.json` | Documentation, desactivee quand `APP_ENV=prod` |
|
|
|
|
## Migrations
|
|
|
|
```bash
|
|
uv run alembic revision --autogenerate -m "libelle"
|
|
uv run alembic upgrade head
|
|
```
|
|
|
|
L'URL de connexion vient de `DATABASE_URL`, pas de `alembic.ini`.
|
|
|
|
La premiere revision ne cree aucune table : elle refuse de s'appliquer si l'extension
|
|
TimescaleDB manque, ce qui arrive quand `db/init` n'a pas ete joue. Le DDL propre a
|
|
TimescaleDB qui ne depend pas du schema applicatif vit dans `db/`, pas ici.
|
|
|
|
## Image Docker
|
|
|
|
Build multi-stage, dependances resolues par uv depuis `uv.lock`, execution sous un
|
|
utilisateur non root, sonde de sante integree.
|
|
|
|
```bash
|
|
docker build -t enervision-backend:local .
|
|
docker run --rm -p 8000:8000 --env-file .env enervision-backend:local
|
|
```
|