Aller au contenu
La double écriture est toujours un bugLecture : 0 %

La double écriture est toujours un bug

Pourquoi écrire dans deux systèmes depuis le même code finit toujours par diverger, les seules sorties correctes, et comment choisir entre outbox et CDC selon ce que chacun vous fait payer.

Par Elias Varen7 min de lectureMembres

PHP
$this->orders->save($order);          // PostgreSQL
$this->search->index($order);         // moteur de recherche
$this->mailer->send($confirmation);   // prestataire de mail

Ces trois lignes passent la revue de code tous les jours. Elles contiennent deux bugs, qui ne dépendent ni du langage, ni du framework, ni de l'ordre des lignes. Entre deux écritures vers deux systèmes qui ne partagent pas de transaction, il existe un instant où le processus peut mourir (déploiement, manque de mémoire, coupure réseau, timeout). À cet instant, un système sait et l'autre ignore. Rien ne viendra corriger l'écart, parce que le seul code qui connaissait l'intention vient de disparaître.

Je dis « toujours » et je le maintiens : la double écriture n'est pas un risque à évaluer, c'est une divergence dont seule la date est inconnue.

Pourquoi aucun aménagement ne la répare

Chaque tentative de sauver les trois lignes échoue pour une raison mécanique.

Changer l'ordre. Si l'on indexe avant d'enregistrer, la recherche montre une commande qui n'existe pas. Si l'on enregistre avant d'indexer, une commande existe et reste introuvable. Vous choisissez la forme de l'incohérence, jamais son absence.

Entourer d'un try/catch et compenser. La compensation est elle-même une écriture vers un autre système, qui peut échouer pour la même raison que la première. Surtout, le cas qui pose problème est la mort du processus, et dans ce cas aucun catch ne s'exécute.

Rejouer en mémoire. Le retry ne survit pas au processus qui le porte.

Mettre le second appel dans la transaction. L'appel externe réussit, puis le COMMIT échoue sur un conflit de sérialisation ou une connexion perdue. Le mail est parti pour une commande annulée. En prime, vous gardez une transaction et ses verrous ouverts pendant un appel réseau.

Le commit en deux phases. Il exige que les deux systèmes le supportent, ce que n'offrent ni une API HTTP, ni la plupart des brokers, ni un moteur de recherche ; et il fait de la disponibilité de l'un la condition des écritures de l'autre.

La double écriture est toujours un bug · Deepstack