Write Service Contract¶
Status: CONTRACT
À quoi sert ce contrat ?¶
Le contrat Write Service définit les règles communes applicables aux services capables de modifier durablement les données de CMonChoix.
Il constitue la frontière officielle entre :
- l'observation et l'audit ;
- la simulation ;
- la validation d'une décision ;
- l'écriture effective.
La règle de transmission est :
Un Write Service applique une décision déjà validée ; il ne fabrique pas cette décision.
Pourquoi isoler les écritures ?¶
Une lecture incorrecte produit un diagnostic faux. Une écriture incorrecte peut modifier durablement des milliers de lignes, casser une projection ou rendre une reprise difficile.
Isoler les mutations dans des services dédiés permet :
- d'identifier immédiatement qu'un traitement écrit ;
- de borner le périmètre avant exécution ;
- de séparer audit et mutation ;
- de tester l'idempotence ;
- de mesurer précisément les effets ;
- de prévoir reprise et rollback ;
- d'éviter qu'un controller, une CLI ou un bootstrap écrive directement par effet de bord.
Position dans le flux¶
Read Service / Audit
↓
Simulation ou comparaison
↓
Validation explicite
↓
Write Service
↓
Persistance contrôlée
↓
Vérification / rapport
Toutes les opérations n'ont pas nécessairement un outil de simulation dédié, mais une écriture sensible ne doit jamais être confondue avec une simple observation.
Types d'opérations¶
Un Write Service peut notamment prendre en charge :
- persistance ou rebuild de projection ;
- réparation validée ;
- nettoyage contrôlé ;
- fusion explicitement autorisée ;
- migration ;
- reclassification ;
- backfill ;
- correction issue d'un audit.
Le fait qu'une opération appartienne à cette liste ne l'autorise pas automatiquement. Chaque service doit définir son propre périmètre, ses préconditions et ses garde-fous.
Entrées attendues¶
Un Write Service reçoit des paramètres applicatifs déjà validés, par exemple :
- identifiants ou clés métier ciblés ;
- run, batch, feed ou verticale concerné ;
- décision ou structure à persister ;
- options d'exécution explicites ;
- contexte de traçabilité ;
- éventuellement un mode
dry-runlorsque le service le prévoit.
Il ne doit pas lire lui-même $_GET, $_POST, les arguments bruts d'une commande ou des globals WordPress. Ces détails appartiennent aux Adapters et entrypoints.
Sortie attendue¶
Une opération d'écriture doit produire un résultat structuré permettant de savoir ce qui s'est réellement passé.
Selon le service, ce résultat contient notamment :
- statut global ;
- nombre d'éléments examinés ;
- nombre d'éléments modifiés ;
- nombre d'éléments déjà conformes ;
- nombre d'éléments ignorés ;
- nombre d'échecs ;
- raisons d'échec ou d'ignorance ;
- identifiant de run, batch ou opération ;
- durée ;
- avertissements.
Les compteurs doivent être réconciliables. Par exemple :
examined = changed + unchanged + skipped + failed
Un simple message « terminé » n'est pas une preuve suffisante qu'une mutation s'est déroulée correctement.
Responsabilités¶
Le Write Service est responsable de :
- faire respecter les préconditions d'écriture ;
- borner le périmètre ciblé ;
- exécuter la persistance prévue ;
- gérer transaction, upsert ou stratégie équivalente lorsque nécessaire ;
- rendre le rejeu idempotent autant que le contrat le permet ;
- rendre visibles les erreurs partielles ;
- produire des métriques et un résultat d'exécution ;
- permettre une reprise contrôlée.
Il n'est pas responsable de :
- résoudre une identité ;
- détecter ou arbitrer un conflit métier ;
- décider quel candidat est correct ;
- inventer une règle de verticale ;
- effectuer un audit sous couvert d'une écriture ;
- produire du HTML ou une réponse HTTP ;
- décider seul qu'une mutation destructive est souhaitable.
Frontière avec les Adapters¶
Les Adapters HTTP, admin ou CLI :
- reçoivent la demande externe ;
- valident et traduisent les paramètres ;
- appellent le service applicatif approprié ;
- traduisent le résultat pour l'utilisateur ou le transport.
Ils ne doivent pas contenir une seconde implémentation de l'écriture métier ou SQL.
Écritures de projection¶
Les projections sont dérivées et reconstruisibles. Leur persistance doit rester séparée du Projection Builder qui construit la représentation en mémoire.
La documentation d'architecture actuelle décrit notamment les services suivants pour cette famille :
CCX_OfferProjectionWriteService;CCX_ProductModelProjectionWriteService;CCX_ProductVariantProjectionWriteService;CCX_ProductSpecificationProjectionWriteService;CCX_ProductGalleryProjectionWriteService.
Le mainteneur doit toutefois vérifier l'implémentation réellement chargée dans le Runtime avant de conclure qu'un service documenté est actif dans tous les chemins d'exécution.
Un entrypoint ou un orchestrateur ne doit pas contourner un Write Service dédié pour appeler directement un writer legacy.
Audit-first et Media Quality¶
Media Quality est documenté avec une politique audit-first : l'observation et le diagnostic sont séparés d'une éventuelle mutation.
Un score, une incohérence ou une suggestion de remplacement ne doit donc pas déclencher implicitement :
- suppression d'image ;
- remplacement d'image ;
- modification de projection ;
- écriture métier.
Toute future mutation de cette famille doit passer par un Write Service distinct, explicitement activé et doté de garde-fous adaptés.
Idempotence¶
Une opération rejouée avec les mêmes paramètres ne doit pas dupliquer ses effets ni dégrader un état déjà valide.
Le service doit autant que possible distinguer :
- réellement modifié ;
- déjà conforme ;
- ignoré par politique ;
- en échec.
L'idempotence est particulièrement importante pour les runs, batches, rebuilds et reprises après interruption.
Reprise et rollback¶
Avant une opération large, la documentation ou l'implémentation du service doit permettre de comprendre :
- comment reprendre après interruption ;
- quelles unités de travail sont déjà appliquées ;
- comment éviter leur duplication ;
- si un rollback est possible ;
- sinon, comment reconstruire ou restaurer l'état antérieur.
« Relancer la commande » n'est une stratégie de reprise sûre que si l'idempotence a été vérifiée.
Garde-fous opérationnels¶
Toute écriture potentiellement large doit proposer autant que possible :
- un mode
dry-runou une simulation équivalente ; - un filtre explicite par run, feed, verticale ou identifiant ;
- une limite de volume ;
- une confirmation opérateur pour les opérations sensibles ;
- une stratégie de reprise ;
- une stratégie de rollback ou une justification documentée de son absence.
Une commande qui écrit doit l'annoncer clairement dans son nom, son aide ou sa sortie. Elle ne doit jamais se présenter comme un audit read-only.
Procédure d'intervention sûre¶
Pour une mutation sensible :
- observer avec un Read Service ou un audit ;
- définir le périmètre exact des données concernées ;
- simuler ou comparer lorsque l'outil existe ;
- valider la décision et les préconditions ;
- sauvegarder ou préparer le rollback si le risque le justifie ;
- exécuter le Write Service sur le périmètre prévu ;
- vérifier les compteurs et erreurs ;
- relire l'état final avec un outil read-only indépendant.
Cette séparation observation → simulation → écriture → vérification doit rester visible dans les procédures d'exploitation.
Auditabilité¶
Toute écriture doit permettre de répondre à :
- quoi a été ciblé ?
- pourquoi l'opération a-t-elle été autorisée ?
- quand a-t-elle été exécutée ?
- quel service et quelle version du code l'ont exécutée ?
- avec quels paramètres ?
- combien d'éléments ont changé ?
- quels éléments ont échoué ou été ignorés ?
- quel rapport ou audit a précédé la mutation lorsque cela s'applique ?
Les logs sont utiles, mais ils ne remplacent pas un résultat structuré et réconciliable.
Erreurs fréquentes de maintenance¶
- ajouter un
UPDATESQL directement dans une commande d'audit ; - faire écrire un composant présenté comme Read Service ;
- considérer un
dry-runcomme sûr sans vérifier qu'il n'appelle aucune persistance ; - relancer aveuglément une opération interrompue sans connaître son idempotence ;
- modifier une projection stockée pour corriger un problème qui vient de la Canonical Identity ;
- laisser un Adapter décider lui-même du métier ;
- conclure qu'un service documenté est actif sans vérifier le chemin runtime réel.
Tests attendus¶
Un Write Service doit être couvert par des tests vérifiant au minimum :
- les préconditions ;
- le périmètre d'écriture ;
- l'absence de mutation en
dry-runlorsqu'il existe ; - l'idempotence du rejeu ;
- la réconciliation des compteurs ;
- la visibilité des erreurs partielles ;
- le respect des invariants métier ;
- la séparation avec les Adapters ;
- l'absence de mutation implicite dans les composants audit-first.
État d'implémentation¶
Ce document est un CONTRACT. Il décrit la frontière que les écritures doivent respecter ; il ne faut pas en déduire que toutes les écritures historiques ont déjà été migrées vers cette forme.
Lorsqu'un chemin legacy existe encore, la bonne démarche est de l'identifier, de vérifier ses effets réels et de le faire converger progressivement vers cette frontière plutôt que de supposer qu'il est déjà conforme.
Invariants¶
- Écriture explicite — aucune mutation par simple chargement d'un bootstrap.
- Décision séparée — le Write Service applique une décision ; il ne la fabrique pas.
- Périmètre borné — les données ciblées sont identifiables avant exécution.
- Traçabilité — toute écriture est attribuable, mesurable et explicable.
- Idempotence — le rejeu ne duplique pas les effets.
- Reprise contrôlée — une interruption ne transforme pas un succès partiel en état opaque.
- Transport neutre — aucun détail HTTP, CLI, admin ou HTML dans le service.
- Projection reconstruisible — une projection n'est jamais traitée comme vérité métier.
- Audit-first préservé — une analyse read-only ne devient jamais implicitement une mutation.