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

  1. L’utilisateur vérifie son panier et confirme l’achat
  2. Le frontend envoie les données de la commande : articles, quantités, adresse de livraison, mode de paiement
  3. Il affiche un spinner pendant qu’il attend la confirmation
  4. Il reçoit la confirmation avec l’ID de la commande et affiche un message de succès

BFF

  1. Il reçoit les données du frontend
  2. Il peut enrichir la requête (résoudre les IDs des produits, valider le format)
  3. Il invoque le microservice de commandes
  4. Il transforme la réponse pour le frontend

Microservice de commandes (ms-orders)

C’est le service qui orchestre la création :

  1. Il valide les données de la commande (les articles existent, les quantités sont valides, l’adresse est complète)
  2. Il calcule le total
  3. Il enregistre la commande dans sa base de données avec l’état pending
  4. Il publie l’événement OrderPlaced sur l’Event Bus
  5. 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)

  1. Il reçoit l’événement OrderPlaced
  2. Il vérifie qu’il y a suffisamment de stock pour chaque article
  3. Il réserve le stock (il le marque comme engagé)
  4. Il publie InventoryReserved ou InventoryInsufficient

Paiements (ms-payments)

  1. Il reçoit l’événement OrderPlaced
  2. Il déclenche le processus d’encaissement auprès du prestataire de paiement
  3. Il publie PaymentCompleted ou PaymentFailed

Notifications (ms-notifications)

  1. Il reçoit l’événement OrderPlaced
  2. Il envoie un email de confirmation à l’utilisateur
  3. 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 :

  1. La commande est créée à l’état pending
  2. Les services traitent leurs parties de manière indépendante
  3. Les événements de résultat mettent à jour l’état de la commande
  4. 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 :

ÉchecCompensation
Le paiement échoue après la réservation d’inventairePublier PaymentFailed → l’inventaire libère le stock
Inventaire insuffisant après le déclenchement du paiementPublier InventoryInsufficient → les paiements annulent l’encaissement
Timeout sans réponse de l’inventaireLa 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 :

  1. Il clique sur « Confirmer l’achat »
  2. Il voit un spinner pendant 1 à 2 secondes
  3. Il voit « Commande #12345 reçue » avec l’état « En cours de traitement »
  4. Il reçoit un email de confirmation
  5. 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.