Livraison at-least-once
La sémantique réseau par défaut de tout EDI réaliste — et la raison d'être de l'idempotence côté récepteur.
Problème
Aucun système distribué ne peut, sans coordination spécifique, garantir une livraison exactement-une-fois en présence de pannes réseau. Quand l'émetteur n'a pas reçu le MDN, il ne peut pas distinguer « le message a été livré et l'ACK est perdu » de « le message n'a pas été livré ». S'il privilégie la fiabilité, il retransmet — produisant des doublons.
Forces
- Le réseau n'est pas fiable. Routeurs, MTU, pare-feu, timeouts TLS, NAT : autant de raisons pour qu'un ACK se perde indépendamment du payload.
- L'émetteur doit pencher du côté de la complétude. Une commande perdue coûte plus cher qu'une commande dédoublonnée.
- Le récepteur peut dédupliquer. C'est le seul à avoir un état cohérent de ce qu'il a déjà accepté.
- Exactement-une-fois pur n'existe pas au niveau transport — il s'obtient seulement en composant at-least-once réseau + déduplication récepteur.
Solution
Accepter explicitement que la pile de transport est at-least-once, documenter le contrat dans la convention partenaire, et investir sur la déduplication côté récepteur (pattern Idempotent Receiver) plutôt que de chercher une exactly-once illusoire. L'émetteur applique du retry avec backoff exponentiel et jitter ; le récepteur tient une table de clés d'idempotence sur une fenêtre.
émetteur ──────► partenaire
│ │
│ MDN/Receipt │
◄────────────────┘ ── perdu ✗
→ l'émetteur ne sait pas si « livré et pas d'ACK »
ou « pas livré ».
→ il retente. Le partenaire reçoit 1 ou N copies.
→ le partenaire doit déduper (Idempotent Receiver).
Implémentation EDI
AS2 est nativement at-least-once : le MDN n'est qu'un accusé applicatif.
AS4 idem, avec eb:Receipt qui peut se perdre. Kafka en
acks=all + enable.idempotence=true côté
producteur fournit at-least-once renforcé par déduplication broker
sur 5 minutes. RabbitMQ avec acknowledgements manuels reproduit la
même sémantique. Tous les middlewares EDI modernes (Sterling B2B,
Mulesoft, BizTalk) annoncent leur SLA en at-least-once et imposent
la déduplication côté hub.
Anti-patterns
- Promettre exactly-once au métier. Le métier conclura à un bug dès que le premier doublon arrivera. Documenter explicitement at-least-once + déduplication.
- Désactiver les retries pour éviter les doublons. Faute moins fréquente, mais plus coûteuse : on échange des doublons visibles contre des pertes silencieuses.
- Déduplication côté émetteur seul. L'émetteur ne sait pas ce que le récepteur a accepté. La dédup doit être chez celui qui voit l'état final.
- Ack avant traitement. Si le receveur acquitte avant d'avoir persisté, un crash perd le message. L'ack doit suivre le commit applicatif (Outbox-style).
Patterns liés
- At-Most-Once — le pendant inverse, sémantique de logs/télémétrie non-critiques.
- Idempotence — le pattern qui rend at-least-once acceptable côté métier.
- Guaranteed Delivery — la garantie broker qui s'ajoute par-dessus.
Sources
- Kleppmann M. — Designing Data-Intensive Applications, O'Reilly 2017, chap. 11 « Stream Processing » (semantics: at-most-once, at-least-once, exactly-once). dataintensive.net
- Apache Kafka — Delivery semantics. kafka.apache.org/documentation/#semantics
- RFC 4130 — MIME-based Secure Peer-to-Peer Business Data Interchange Using HTTP, Applicability Statement 2 (AS2). §7.3 décrit l'acquittement non-fiable du MDN. rfc-editor.org/rfc/rfc4130