Créer une commande
Flux de création d'une commande : depuis le frontend jusqu'au microservice de commandes, avec publication d'événements et coordination avec l'inventaire et les paiements.
Pourquoi la création de commande est un flux complexe
Créer une commande ne consiste pas simplement à enregistrer un enregistrement dans une base de données. C’est un flux qui implique plusieurs services, des validations métier, la réservation d’inventaire, le déclenchement du paiement et des notifications. C’est l’exemple parfait de la façon dont la communication synchrone et asynchrone coexistent dans un même cas d’usage.
Le flux complet
sequenceDiagram
participant FE as Frontend
participant GW as API Gateway
participant BFF as BFF
participant ORD as ms-orders
participant DB as Orders DB
participant EB as Event Bus
participant INV as ms-inventory
participant PAY as ms-payments
participant NOT as ms-notifications
FE->>GW: POST /orders
GW->>GW: Auth, rate limiting
GW->>BFF: Forward
BFF->>ORD: Crear orden
ORD->>ORD: Validar datos de la orden
ORD->>DB: Guardar orden (estado: pending)
DB-->>ORD: OK
ORD->>EB: Publicar OrderPlaced
ORD-->>BFF: Orden creada (id, estado)
BFF-->>GW: Respuesta para UI
GW-->>FE: 201 Created + orden
Note over EB: Procesamiento asíncrono
EB->>INV: OrderPlaced
INV->>INV: Reservar stock
INV->>EB: InventoryReserved
EB->>PAY: OrderPlaced
PAY->>PAY: Iniciar proceso de pago
EB->>NOT: OrderPlaced
NOT->>NOT: Enviar confirmación al usuario
Phase synchrone : créer la commande
La première partie du flux est synchrone. L’utilisateur attend une confirmation que sa commande a bien été reçue.
Frontend
- L’utilisateur vérifie son panier et confirme l’achat
- Le frontend envoie les données de la commande : articles, quantités, adresse de livraison, mode de paiement
- Il affiche un spinner pendant qu’il attend la confirmation
- Il reçoit la confirmation avec l’ID de la commande et affiche un message de succès
BFF
- Il reçoit les données du frontend
- Il peut enrichir la requête (résoudre les IDs des produits, valider le format)
- Il invoque le microservice de commandes
- Il transforme la réponse pour le frontend
Microservice de commandes (ms-orders)
C’est le service qui orchestre la création :
- Il valide les données de la commande (les articles existent, les quantités sont valides, l’adresse est complète)
- Il calcule le total
- Il enregistre la commande dans sa base de données avec l’état
pending - Il publie l’événement
OrderPlacedsur l’Event Bus - Il renvoie la commande créée au BFF
Point clé : la commande est enregistrée et l’événement est publié dans la même opération (idéalement en utilisant le pattern Outbox pour garantir la cohérence).
Phase asynchrone : coordination entre services
Une fois l’événement OrderPlaced publié, plusieurs services réagissent de manière indépendante.
Inventaire (ms-inventory)
- Il reçoit l’événement
OrderPlaced - Il vérifie qu’il y a suffisamment de stock pour chaque article
- Il réserve le stock (il le marque comme engagé)
- Il publie
InventoryReservedouInventoryInsufficient
Paiements (ms-payments)
- Il reçoit l’événement
OrderPlaced - Il déclenche le processus d’encaissement auprès du prestataire de paiement
- Il publie
PaymentCompletedouPaymentFailed
Notifications (ms-notifications)
- Il reçoit l’événement
OrderPlaced - Il envoie un email de confirmation à l’utilisateur
- Il peut envoyer une notification push si l’application le prend en charge
Coordination et états de la commande
La commande passe par plusieurs états selon les événements qu’elle reçoit :
stateDiagram-v2
[*] --> Pending: OrderPlaced
Pending --> Confirmed: InventoryReserved + PaymentCompleted
Pending --> Cancelled: InventoryInsufficient
Pending --> Cancelled: PaymentFailed
Confirmed --> Shipped: ShipmentCreated
Shipped --> Delivered: ShipmentDelivered
Cancelled --> [*]
Delivered --> [*]
Le microservice de commandes écoute les événements d’inventaire et de paiements pour mettre à jour l’état :
- Si les deux réussissent →
confirmed - Si l’inventaire échoue →
cancelled(et le paiement est annulé s’il a déjà été encaissé) - Si le paiement échoue →
cancelled(et l’inventaire réservé est libéré)
Le problème de la cohérence
Dans ce flux, il n’existe pas de transaction distribuée qui garantisse que tout se produise de manière atomique. À la place, on utilise la cohérence à terme :
- La commande est créée à l’état
pending - Les services traitent leurs parties de manière indépendante
- Les événements de résultat mettent à jour l’état de la commande
- Si quelque chose échoue, des compensations sont exécutées (libérer le stock, annuler le paiement)
C’est le pattern Saga en action : une séquence de transactions locales coordonnées par des événements.
Compensations
Lorsqu’un échec survient après que d’autres services ont déjà agi, des compensations sont nécessaires :
| Échec | Compensation |
|---|---|
| Le paiement échoue après la réservation d’inventaire | Publier PaymentFailed → l’inventaire libère le stock |
| Inventaire insuffisant après le déclenchement du paiement | Publier InventoryInsufficient → les paiements annulent l’encaissement |
| Timeout sans réponse de l’inventaire | La commande passe à cancelled après un délai limite |
Idempotence
Chaque consommateur doit être idempotent. Si l’événement OrderPlaced est livré deux fois :
- L’inventaire ne doit pas réserver le stock deux fois
- Les paiements ne doivent pas encaisser deux fois
- Les notifications ne doivent pas envoyer deux emails
La façon la plus courante d’y parvenir est d’enregistrer l’ID de l’événement traité et de le vérifier avant d’agir.
Ce que voit l’utilisateur
Du point de vue de l’utilisateur :
- Il clique sur « Confirmer l’achat »
- Il voit un spinner pendant 1 à 2 secondes
- Il voit « Commande #12345 reçue » avec l’état « En cours de traitement »
- Il reçoit un email de confirmation
- Il peut consulter l’état de la commande, qui se met à jour au fur et à mesure que les services traitent
L’utilisateur n’a pas besoin de savoir que 4 services se coordonnent en coulisses. Il ne voit qu’un flux clair.
Résumé
La création d’une commande combine communication synchrone (pour donner une réponse rapide à l’utilisateur) et communication asynchrone (pour coordonner l’inventaire, les paiements et les notifications). La cohérence est obtenue au moyen d’événements et de compensations, et non de transactions distribuées. Chaque service est responsable de sa partie et réagit aux événements des autres.