Event Store et moteur de replay¶
Statut¶
Spécification d'infrastructure du cœur de plateforme (M3).
Pourquoi ce document existe¶
Cette page décrit le stockage historique des événements et le mécanisme capable de les rejouer.
Deux notions sont à distinguer :
- Event Store : stockage append-only des événements ;
- Replay Engine : mécanisme qui relit ces événements pour reconstruire un état dérivé.
Pour une personne qui reprend le projet, il faut surtout retenir qu'un Event Store n'est pas une table métier classique que l'on corrige avec des UPDATE manuels.
Principe général¶
Domain Events
↓
Event Store
↓
Replay Engine
↓
État dérivé reconstruit
Dans cette architecture, l'historique est conservé en ajoutant des événements, pas en réécrivant les événements anciens.
Modèle append-only¶
Append-only signifie : on ajoute à la fin.
Une fois enregistré, un événement n'est normalement :
- ni modifié ;
- ni supprimé ;
- ni remplacé.
Cela permet de conserver une trace de ce qui s'est produit et de rejouer cette histoire de façon reproductible.
Structure d'un événement stocké¶
Un événement doit notamment disposer de :
event_id;event_type;aggregate_id;aggregate_type;version;timestamp;payload.
Le payload contient les données du fait enregistré. L'Event Store ne doit pas interpréter lui-même leur sens métier.
Partitionnement¶
La spécification prévoit que les événements puissent être organisés principalement par aggregate_id.
L'intérêt est simple : pour reconstruire un Product précis, il est inutile de relire l'intégralité de l'histoire de tous les produits si le stockage permet d'accéder directement à son flux d'événements.
Le Replay Engine¶
Le moteur de replay relit l'histoire pour reconstruire un état.
Il peut servir à :
- reconstruire une projection ;
- vérifier une migration ;
- diagnostiquer une divergence ;
- reconstituer un état après incident ;
- tester qu'une nouvelle version produit le même résultat attendu.
Trois modes de replay¶
Replay complet¶
Relit tout l'historique prévu par le périmètre et reconstruit l'état depuis le début.
C'est l'opération la plus large et potentiellement la plus coûteuse.
Replay d'un agrégat¶
Relit uniquement les événements d'un ProductId ou d'un agrégat donné.
C'est généralement préférable lorsqu'un problème est localisé.
Replay sur une période¶
Relit les événements compris entre deux instants.
Ce mode peut être utile pour analyser une régression apparue sur une fenêtre donnée.
Idempotence¶
Un replay doit être idempotent :
même historique + mêmes règles = même état final
Relire deux fois le même événement ne doit pas créer deux produits, deux projections ou deux mutations identiques.
Ordre¶
Pour un même agrégat, les événements doivent être traités dans l'ordre prévu par leur version ou leur séquence logique.
Un ordre global entre tous les agrégats n'est pas requis.
Déduplication¶
Si un événement est reçu deux fois, le consommateur doit pouvoir reconnaître qu'il a déjà été pris en compte et éviter une seconde application incorrecte.
C'est une conséquence directe de la livraison at-least-once décrite dans le modèle global d'événements.
Snapshots¶
Un snapshot est une photographie intermédiaire d'un état utilisée pour éviter de rejouer un historique très long depuis le début.
Mais un snapshot n'est pas la source de vérité. Il doit pouvoir être régénéré à partir des données ou événements autoritatifs.
Gestion des erreurs¶
La spécification impose notamment que :
- un échec d'écriture d'événement soit détecté et traité ;
- un événement corrompu ne soit pas ignoré silencieusement ;
- un échec de replay ne corrompe pas l'historique stocké.
Frontière d'architecture¶
L'Event Store est de l'infrastructure.
Il ne doit pas :
- décider qu'un Product correspond à un autre ;
- interpréter un conflit ;
- modifier le contenu historique ;
- contenir une règle Product ou Catalog ;
- devenir un substitut au Domain Core.
Il stocke et restitue des faits. Les décisions appartiennent aux couches métier.
Attention : spécification cible et Runtime réel¶
Cette page décrit une architecture M3 et porte historiquement le statut IMPROVE.
Cela signifie qu'il ne faut pas supposer qu'un Event Store complet et tous les modes de replay décrits ici sont déjà câblés en production simplement parce que cette spécification existe.
Avant toute opération réelle, vérifier :
- le code effectivement chargé ;
- les points d'entrée Runtime actifs ;
- les commandes disponibles ;
- les tests et certifications correspondants ;
- la documentation d'état Runtime courant.
Cette distinction est particulièrement importante pour une personne qui reprend le projet : une page de design peut décrire la cible sans prouver que la capacité est déjà opérationnelle.
Diagnostic pratique¶
Si une projection semble incohérente et qu'un replay est envisagé :
- confirme d'abord que la source de vérité amont est correcte ;
- détermine si le mécanisme de replay correspondant existe réellement dans le Runtime actuel ;
- privilégie un périmètre ciblé plutôt qu'un replay global ;
- utilise une simulation ou un environnement isolé lorsque possible ;
- compare avant/après ;
- ne lance pas une reconstruction destructive en production sur la seule base de cette spécification.
Position dans le flux logique¶
Product Domain → émet des événements
Runtime → transporte / orchestre
Event Store → conserve l'historique
Replay Engine → relit l'historique
Projection → reconstruit les vues
Catalog → expose les vues dérivées
Décision¶
Statut historique de la spécification : IMPROVE.
Elle décrit la responsabilité cible de persistance événementielle et de replay. L'état d'activation réel doit toujours être vérifié dans le Runtime courant.