Spécimen architectural de R&D 02 — Référence : couche d’intégration d’entreprise
File d’événements tolérante aux pannes : acceptation durable, reprises bornées, effet idempotent
Spécimen architectural de R&D : recherche et développement du studio, construit et mesuré dans ce dépôt. Ce n’est pas un travail de client et il ne décrit aucun client. Chaque chiffre de cette page est mesuré ou calculé, et sa méthode est indiquée.
Question de conception
Quand un système d’une chaîne cale, les événements ne doivent ni disparaître ni être appliqués deux fois. Une petite machine à états sans dépendances peut-elle offrir une livraison au moins une fois avec un effet au plus une fois, survivre à un redémarrage et à un canal mort, et le montrer sur des scénarios de panne déterministes ?
Niveau de preuve B : une implémentation de référence vérifiée par des tests exécutables. Elle n’est branchée sur aucun système de client ; volumes, identifiants et contexte juridique sortent de ce que ce spécimen affirme.
I
Contrainte et tolérance
Trois modes de défaillance, chacun avec une tolérance écrite.
Perte : un événement acquitté auprès de son producteur doit survivre à un redémarrage et à un canal mort. L’acceptation est une écriture durable faite avant l’acquittement.
Répétition : les réseaux répètent. La livraison est au moins une fois, donc le récepteur applique un identifiant d’événement une fois et écarte la répétition, quel que soit celui qui le renvoie.
Absence de borne : aucun événement ne peut être rejoué sans fin ni retenu sans fin. Les tentatives, l’âge et l’issue à chaque limite (envoyé aux lettres mortes, conservé, jamais abandonné) sont écrits comme politique.
II
Architecture
Une machine à états sans minuteur et sans entrée ni sortie propres.
L’appelant fournit l’horloge, le stockage durable et le canal, si bien que le même code s’exécute dans une simulation déterministe, dans le navigateur et, avec un vrai stockage et un vrai canal, dans un projet.
États : en attente, nouvel essai, garé, livré, mort. Les envois échoués sont rejoués avec un recul exponentiel. Après une série d’échecs et une sonde de santé échouée, le circuit s’ouvre : les événements sont garés dans le stockage et une sonde peu coûteuse teste le canal jusqu’à son retour, puis l’arriéré est écoulé dans l’ordre.
Isolation des événements toxiques : un événement qui échoue sur un canal sain est un mauvais événement, pas un canal mort. Il est rejoué dans son budget, puis envoyé aux lettres mortes, et le circuit reste fermé ; un mauvais événement n’arrête donc pas la file derrière lui plus longtemps que ce budget.
III
Vérification
Des scénarios déterministes et un ensemble fixe d’invariants.
Parmi les scénarios : un canal en panne pendant vingt secondes, un canal instable, des acquittements perdus sur 30 % des envois, un événement toxique, un événement obstiné, des redémarrages pendant une panne, un producteur qui envoie deux fois, et tout à la fois. Chacun utilise une horloge virtuelle et un générateur à graine : ni minuteurs, ni réseau.
Sur chaque scénario, les tests de contrat affirment qu’aucun événement accepté n’est perdu, qu’aucun n’est appliqué deux fois, que l’ordre d’acceptation est conservé et qu’aucun événement n’est envoyé plus souvent que la politique ne le permet.
Le tableau des résultats de la documentation est généré à partir du code et comparé à lui par un test ; la preuve est donc ce que le code fait aujourd’hui.
Où s’appliquent les niveaux : cette file est de niveau de preuve B (une référence vérifiée par des tests). Le webhook signé à livraison idempotente que ce site exécute en production est de niveau A.
IV
Résultat mesuré et limites
Calculé à partir du code que les tests exécutent.
Mesuré
Ces chiffres sont calculés lors du dessin de la page, en exécutant les scénarios que les tests de contrat exécutent. Ils sont déterministes : identiques à chaque requête.
- Scénarios exécutés
- 9
- 9 sur 9 ont tenu chaque invariant
- Événements acceptés
- 370
- sur l’ensemble des scénarios
- Événements perdus
- 0
- chaque événement accepté appliqué, envoyé aux lettres mortes ou encore en file
- Événements appliqués deux fois
- 0
- 56 répétitions ont été écartées
Calculé à partir de lib/arch/scenarios.ts par le simulateur qu’exécutent les tests de contrat, lors du dessin de cette page. 5 événements ont été envoyés aux lettres mortes (conservés, jamais abandonnés) : événements toxiques ou obstinés, par conception.
Compromis et limites
Ce que coûte ce modèle, et où il a besoin du client.
Au moins une fois, c’est des répétitions
Les répétitions sont voulues par la conception ; le récepteur doit donc les gérer et retenir les identifiants plus longtemps que la plus longue durée pendant laquelle la file peut réessayer.
L’ordre coûte de la disponibilité
Avec un ordre strict, un événement qui échoue retarde ceux qui le suivent jusqu’à son succès ou son envoi aux lettres mortes. À désactiver pour des événements indépendants.
Le stockage est une dépendance
La durabilité vaut ce que vaut le stockage donné à la file. Son choix (une base de données, une file gérée) et ses propres garanties relèvent du projet.
Mesuré sur
- TypeScript · no dependencies
- Virtual clock · seeded generator
- Node · browser