Couche de synchronisation runtime du Catalog¶
Statut¶
Document d'architecture pour la transmission du projet.
À quoi sert cette couche ?¶
La Runtime Synchronization Layer, ou couche de synchronisation runtime, organise la propagation des changements du Product Domain et des offres normalisées vers les projections du Catalog.
Elle répond à une question simple :
lorsqu'un produit ou son état amont change, comment faire en sorte que le catalogue finisse lui aussi par refléter ce changement ?
Elle ne décide pas de la vérité métier. Elle transporte et orchestre les changements entre les composants responsables.
Vue simplifiée¶
Product Domain / offres normalisées
(source amont)
↓ changement / finalisation
Couche de synchronisation runtime
↓ déclenchement
Moteur de projection Catalog
↓ reconstruction / mise à jour
Catalog Domain
(structures de lecture)
↓
Frontend
La cohérence éventuelle¶
Le système suit un modèle de cohérence éventuelle (eventual consistency).
Cela signifie qu'après une modification de l’état amont, le Catalog peut être temporairement en retard. Ce retard n'est acceptable que si le mécanisme de synchronisation permet ensuite au catalogue de converger automatiquement vers l'état attendu et rend les échecs observables.
Exemple :
14:00:00 état amont mis à jour
14:00:01 ancienne projection encore lisible
14:00:03 projection recalculée
14:00:04 catalogue cohérent avec l'amont
La projection ne devient pas source de vérité pendant cette période.
Responsabilités¶
Cette couche doit notamment :
- détecter ou recevoir les changements utiles ;
- capturer les événements ou fins de run utiles à la projection ;
- déclencher les mises à jour du Catalog ;
- empêcher qu'un même événement produise plusieurs effets indésirables ;
- coordonner les reconstructions ;
- permettre un rejeu lorsque cela est nécessaire ;
- rendre les échecs observables et récupérables.
Implémentation CURRENT du refresh produit¶
La finalisation d’un run marchand réussi ne s’arrête pas à l’écriture de ccx_offers_norm_v2.
Le chemin CURRENT est :
upsertNormalizedOffers(feed, run)
↓
ccx_sync_refresh_product_projections(feed)
↓
ccx_product_canonical_projection_refresh()
↓
rebuild Product Models pour les verticales concernées
↓
finalisation du run
Le refresh de ccx_canonical_products_v1 est donc une dépendance de correction du sync. S’il échoue, la finalisation signale une erreur critique au lieu de déclarer le run réussi avec une projection silencieusement obsolète.
Le refresh canonical utilise un lock dédié et appelle actuellement un rebuild global de la projection à partir de toutes les lignes ccx_offers_norm_v2 ayant un product_identity_key non vide.
Cette stratégie globale est correcte pour la convergence actuelle mais n’est pas la stratégie de scalabilité cible ; elle est suivie comme dette technique.
Événements d'entrée¶
Selon l'implémentation, la couche peut réagir à des événements tels que :
ProductCreated— création d'un Product ;ProductUpdated— modification d'un Product ;ProductVariantChanged— changement d'une variante ;ProductObservationAdded— nouvelle observation ;ProductConflictCreated— conflit détecté ;ProductConflictResolved— conflit résolu ;- finalisation réussie d’un run marchand ;
- replay explicite d’une offre.
Les noms exacts peuvent évoluer. Ce qui compte architecturalement est la signification du changement et la capacité à le traiter correctement.
Actions de sortie¶
La couche peut demander des opérations telles que :
CatalogProjectionUpdate— mise à jour d'une projection ;CatalogItemRebuild— reconstruction d'un élément catalogue ;CatalogViewRefresh— rafraîchissement d'une vue ;CatalogCollectionUpdate— mise à jour d'une collection ;- refresh ou rebuild d’une projection persistée explicitement identifiée.
Ces actions sont des demandes d'orchestration. Elles ne doivent pas contenir la décision métier sur l'identité du Product.
Trois modes à connaître¶
Mise à jour incrémentale¶
C'est le mode cible lorsque le périmètre affecté peut être déterminé proprement : seul le périmètre concerné par un changement est recalculé.
Avantage : plus rapide qu'une reconstruction complète.
Condition importante : le résultat final doit converger vers celui qu'aurait produit un rebuild complet avec les mêmes données et règles.
Reconstruction complète¶
Un full rebuild peut être nécessaire lorsque :
- le schéma ou la structure de projection change ;
- une règle majeure de projection évolue ;
- une dérive de cohérence est détectée ;
- les données dérivées ne sont plus considérées comme fiables.
Le rebuild repart des sources autoritatives ou amont certifiées et régénère les projections.
ccx_canonical_products_v1 utilise actuellement ce mode complet à chaque refresh canonical.
Rejeu¶
Le replay consiste à retraiter un événement ou un périmètre déjà connu.
Le replay d’offre CURRENT distingue dry-run et apply. En mode apply, l’offre et ses écritures associées sont commitées, puis la projection canonical est rafraîchie.
Si ce refresh post-commit échoue, l’échec est remonté explicitement. La donnée d’offre déjà commitée ne doit pas être compensée par une modification manuelle de la projection : il faut rejouer le refresh/rebuild jusqu’à convergence.
Idempotence : une règle essentielle¶
Une opération est idempotente lorsqu'on peut la rejouer sans créer de corruption ou de doublon.
Exemple attendu :
traiter événement X une fois → état A
traiter événement X deux fois → toujours état A
Pas :
traiter événement X deux fois → deux CatalogItem identiques
Cette propriété est essentielle parce qu'un système réel peut retenter une opération après un timeout ou une panne.
Ordre des événements¶
Lorsque cela est possible, les événements concernant un même ProductId doivent être traités dans un ordre cohérent.
Sinon, une ancienne modification pourrait arriver après une plus récente et produire une projection obsolète.
L'architecture doit donc prendre en compte :
- l'ordre ;
- la déduplication ;
- les retries ;
- la version ou la fraîcheur de l'état traité lorsque nécessaire ;
- les locks de reconstruction lorsque plusieurs chemins peuvent déclencher le même refresh.
Gestion des erreurs¶
Une panne de synchronisation ne doit pas corrompre la vérité Product ni être masquée par le frontend.
Le comportement attendu est plutôt :
changement amont valide
↓
échec de projection
↓
erreur observable
↓
retry / replay / rebuild
↓
health check
↓
Catalog à nouveau cohérent
Pour les projections produit CURRENT, ccx health projections fournit notamment le contrôle de couverture missing_canonical_product_identity.
Il faut éviter les mécanismes où l'échec d'une projection entraîne une modification destructive de la source simplement pour faire disparaître l'erreur.
Frontière d'architecture¶
La couche de synchronisation ne doit pas :
- modifier les règles du Product Domain ;
- résoudre l'identité canonique ;
- inventer des attributs ;
- interpréter directement une logique spécifique marchand ;
- devenir elle-même un moteur métier ;
- considérer une projection comme la source de vérité.
Son rôle est orchestration + propagation + récupération.
Architecture événementielle : attention au vocabulaire¶
Le système est pensé selon des principes événementiels, même si l'implémentation actuelle est hybride et comprend des finalisations synchrones de run.
Il ne faut donc pas déduire de cette documentation qu'un Kafka ou un bus distribué particulier est obligatoirement déployé aujourd'hui.
Une évolution future pourrait utiliser :
- une abstraction de bus d'événements ;
- une file distribuée ;
- un moteur de traitement de flux.
Mais la technologie choisie reste un détail d'infrastructure tant que le contrat d'architecture est respecté.
Comment diagnostiquer une désynchronisation¶
Si la source amont est correcte mais que le catalogue montre encore une ancienne valeur ou redirige vers un fallback inattendu :
1. Vérifier l'état amont autoritatif / normalisé
↓
2. Vérifier que le changement a été détecté ou finalisé
↓
3. Vérifier que la synchronisation a déclenché la projection
↓
4. Exécuter le health check de projection
↓
5. Vérifier le résultat du moteur de projection
↓
6. Vérifier l'écriture de la projection
↓
7. Vérifier que le frontend lit la projection attendue
Cette chaîne est beaucoup plus sûre qu'un UPDATE ou INSERT manuel dans une table dérivée.
Pour la reprise du projet¶
Retenir quatre mots :
propager, rejouer, converger, observer.
La synchronisation transporte les changements ; elle doit pouvoir être rejouée ; le catalogue doit converger vers la vérité ; et les échecs doivent être visibles.