Aller au contenu

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 :

  1. le code effectivement chargé ;
  2. les points d'entrée Runtime actifs ;
  3. les commandes disponibles ;
  4. les tests et certifications correspondants ;
  5. 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é :

  1. confirme d'abord que la source de vérité amont est correcte ;
  2. détermine si le mécanisme de replay correspondant existe réellement dans le Runtime actuel ;
  3. privilégie un périmètre ciblé plutôt qu'un replay global ;
  4. utilise une simulation ou un environnement isolé lorsque possible ;
  5. compare avant/après ;
  6. 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.

À lire ensuite