91 lines
3.2 KiB
ReStructuredText
91 lines
3.2 KiB
ReStructuredText
Modèle asynchrone et codes de retour
|
|
====================================
|
|
|
|
Toute création et toute suppression sont **asynchrones**. C'est le point qui surprend le plus
|
|
souvent à l'intégration : un ``202`` ne dit pas que la ressource existe, il dit que la demande
|
|
a été acceptée et enregistrée.
|
|
|
|
Les deux temps d'une requête
|
|
----------------------------
|
|
|
|
.. mermaid::
|
|
|
|
sequenceDiagram
|
|
participant C as Appelant
|
|
participant A as API
|
|
participant W as Worker
|
|
C->>A: POST /subnets
|
|
A->>A: Prepare — valide, écrit "creating"
|
|
A-->>C: 202 + ressource en creating
|
|
A->>W: Dispatch (file d'attente)
|
|
W->>W: Execute — netns, netif, dhcp
|
|
W->>W: état → running (ou error)
|
|
C->>A: GET /subnets/<name>
|
|
A-->>C: 200 + state
|
|
|
|
**Prepare** est synchrone, dans le handler HTTP : il valide l'état, écrit l'état initial en base
|
|
et répond. **Execute** est asynchrone : il fait le travail réseau réel, puis positionne l'état
|
|
final.
|
|
|
|
Conséquence directe : un échec d'``Execute`` ne peut pas être remonté dans la réponse HTTP. Il
|
|
se lit dans l'état de la ressource, qui passe à ``error``.
|
|
|
|
Attendre correctement
|
|
---------------------
|
|
|
|
Il n'y a pas de webhook ni de long-polling : l'appelant interroge ``GET /<type>/<name>`` jusqu'à
|
|
un état stable.
|
|
|
|
.. code-block:: bash
|
|
|
|
until [ "$(curl -sf http://127.0.0.1:8080/subnets/sn-000001 | jq -r .state)" = running ]; do
|
|
sleep 2
|
|
done
|
|
|
|
Trois règles pour un appelant robuste :
|
|
|
|
* **Toujours borner l'attente.** Côté agent, ``dispatcher.timeout_seconds`` (300 s par défaut)
|
|
borne les opérations qui attendent une transition ; l'appelant doit avoir sa propre borne.
|
|
* **Traiter ``error`` comme terminal, pas comme un échec transitoire.** Un ``Execute`` en échec
|
|
ne se rejoue pas tout seul.
|
|
* **Ne pas enchaîner sans vérifier.** Créer un subnet dont le VPC est encore en ``creating``
|
|
échoue en 422 ; démarrer une VM sur un subnet en ``creating`` ou ``running`` est en revanche
|
|
accepté.
|
|
|
|
Codes de retour
|
|
---------------
|
|
|
|
.. list-table::
|
|
:header-rows: 1
|
|
:widths: 12 88
|
|
|
|
* - Code
|
|
- Signification
|
|
* - ``202``
|
|
- demande acceptée et enregistrée ; l'état passera à ``running`` ou ``error``
|
|
* - ``200``
|
|
- lecture réussie (``GET``)
|
|
* - ``400``
|
|
- champ obligatoire manquant, corps invalide, ``iface_type`` inconnu, base64 invalide
|
|
* - ``404``
|
|
- ressource inexistante
|
|
* - ``409``
|
|
- conflit d'existence ou d'état : ressource déjà créée, ou suppression depuis un état qui
|
|
ne l'autorise pas ; pour un VPC, subnets encore présents
|
|
* - ``422``
|
|
- dépendance absente ou pas prête : VPC parent d'un subnet, subnet d'une VM
|
|
* - ``500``
|
|
- erreur interne
|
|
|
|
Le corps d'erreur est uniforme : ``{"error": "…"}``.
|
|
|
|
Idempotence
|
|
-----------
|
|
|
|
Les créations ne sont **pas** idempotentes : recréer une ressource existante donne 409, pas 202.
|
|
Un appelant qui rejoue une requête après un timeout réseau doit donc traiter 409 comme
|
|
« déjà fait », après avoir vérifié l'état par un ``GET``.
|
|
|
|
Les suppressions depuis l'état ``error`` sont acceptées mais **best-effort** : les ressources
|
|
système peuvent n'avoir été créées que partiellement, et il n'y a pas de rollback — voir
|
|
:doc:`/concepts/cycle-de-vie`.
|