Passer au contenu
DedicatedPHP Contact

Comment récupérer des processus PHP en échec sans dupliquer les effets secondaires

Apprenez à reprendre des flux PHP à partir de points sûrs, à compenser leurs effets et à définir des limites opérationnelles sans dupliquer paiements, envois ni enregistrements.

Diagramme d’un processus PHP avec étapes persistées, tentatives contrôlées et examen manuel en cas de résultats ambigus

Lorsqu’un processus en plusieurs étapes échoue, le relancer entièrement peut répéter des effets qui se sont déjà produits : créer deux commandes, envoyer deux notifications ou importer deux fois le même enregistrement. La récupération partielle des processus PHP en échec consiste à déterminer quelles étapes sont confirmées, lesquelles peuvent être répétées sans risque et lesquelles nécessitent une compensation ou une vérification humaine.

La décision dépend de la sémantique de chaque opération, et pas seulement de l’endroit où une exception s’est produite. Par exemple, une réponse perdue d’une API ne prouve pas que le système externe a rejeté la requête. Le processus a pu aboutir et la connexion échouer avant que PHP ne reçoive le résultat. Concevoir pour ce cas évite de confondre une exécution interrompue avec une exécution qui n’a jamais eu lieu.

Choisir entre réessayer, reprendre et compenser

Choisir entre réessayer, reprendre et compenser — guía visual de DedicatedPHP

Une nouvelle tentative complète réexécute toutes les étapes. Elle convient lorsque l’ensemble du flux est idempotent — le répéter laisse le même état final — ou lorsqu’aucun effet externe ne s’est encore produit. Si aucune de ces conditions ne peut être garantie, le relancer sans inspection est risqué.

Reprendre signifie continuer à partir de la première étape qui n’est pas confirmée. Cela nécessite d’enregistrer l’état des étapes et leurs résultats, ainsi que de pouvoir récupérer ou vérifier l’effet d’un appel dont le résultat est ambigu. Il ne s’agit pas de sauter tout ce qui semble terminé : des preuves persistées sont nécessaires.

Compenser consiste à exécuter une action qui contrebalance un effet antérieur, comme l’annulation d’une réservation. Cela ne restaure pas toujours exactement l’état initial : une notification déjà envoyée ne peut pas être retirée, et un paiement capturé peut nécessiter un remboursement soumis à son propre délai et à son propre enregistrement. Une compensation est donc une opération métier explicite, et non une annulation automatique de la transaction de base de données.

Modéliser les étapes avec des états et des résultats persistés

Représentez le flux sous la forme d’une séquence ou d’une machine à états dont les étapes ont des noms stables, des entrées identifiables et des résultats persistés. Un modèle initial pourrait comprendre des états tels que pending, running, succeeded, retryable, failed et manual_review. Définissez les transitions autorisées et empêchez un processus de passer à un état final sans enregistrer les preuves nécessaires.

Un enregistrement par processus peut comprendre un identifiant stable, le type de flux, l’état global, la version de la définition du processus, les dates de début et de mise à jour, le numéro de tentative et le motif de la dernière transition. Chaque étape doit enregistrer son état, un identifiant d’opération, des horodatages et une référence au résultat pertinent. Ne persistez que les informations nécessaires à la reprise ou à l’explication du résultat ; ne copiez pas sans discernement les réponses complètes des API ni les secrets.

En PHP, le coordinateur peut séparer la transition d’état de l’exécution de l’étape. La mise à jour doit être atomique lorsque plusieurs workers peuvent prendre en charge le même travail : utilisez une transaction ou un mécanisme de verrouillage approprié et consignez qui a pris en charge le processus et jusqu’à quand. Un verrou avec expiration doit permettre de récupérer les tâches abandonnées sans considérer comme terminée une étape restée à mi-parcours.

Définir des points de contrôle sans supposer une exécution exactement une fois

Enregistrez un point de contrôle après chaque résultat que le système peut confirmer de manière fiable. Pour les opérations locales, il peut s’agir d’une transaction qui enregistre ensemble la modification métier et l’état de l’étape. Pour un appel externe, il n’existe pas de transaction commune entre la base de données et le fournisseur : le processus peut s’arrêter après l’action du fournisseur, mais avant que PHP n’enregistre la réponse.

À cette frontière, utilisez une clé d’idempotence si le fournisseur la prend en charge, dérivée d’un identifiant stable du processus et de l’étape. Si ce n’est pas le cas, consultez l’état distant à l’aide d’un identifiant d’opération avant de répéter la requête. En l’absence de prise en charge de l’idempotence et de consultation fiable, considérez le résultat comme ambigu et transmettez le cas pour examen. Un délai d’attente dépassé ne suffit pas à conclure que l’opération n’a pas eu lieu.

Pour les tâches asynchrones, le modèle de boîte d’envoi transactionnelle (outbox) permet d’enregistrer la modification locale et le message en attente au sein d’une même transaction. Un worker remet ensuite le message ; le consommateur doit lui aussi tolérer les doublons, par exemple en enregistrant les identifiants traités. Ces mécanismes réduisent les incohérences, mais ne transforment pas automatiquement toute une intégration distribuée en opération atomique.

Fixer les limites de réexécution et de compensation

Définissez pour chaque étape quelles erreurs sont transitoires, lesquelles sont définitives et lesquelles laissent le résultat inconnu. Les erreurs transitoires peuvent justifier des tentatives avec un délai croissant et une variation aléatoire ; fixez un nombre maximal de tentatives et un délai total. Les erreurs de validation ou de permissions ne s’améliorent généralement pas avec de nouvelles tentatives : mieux vaut arrêter le flux, corriger la cause et décider si une nouvelle exécution est appropriée.

Documentez pour chaque effet externe s’il peut être répété, consulté, compensé ou s’il ne peut pas être annulé. Conservez le résultat lorsque l’opération est valide et que la répétition est plus dommageable que l’état partiel ; ne compensez que s’il existe une action métier sûre et autorisée. Arrêtez le processus et faites remonter le cas lorsque les données ne permettent pas de déterminer ce qui s’est passé, que la compensation échoue elle aussi ou que l’action a un impact financier, juridique ou sur les clients nécessitant une approbation.

Une politique de compensation doit préciser l’ordre, les conditions, le responsable et le résultat attendu. Enregistrez la compensation comme une nouvelle étape, liée à l’effet d’origine, au lieu d’en effacer l’historique. Les opérations peuvent ainsi distinguer une action jamais effectuée, une action effectuée et une action compensée.

Donner aux équipes opérationnelles les moyens d’agir et le contexte nécessaire

La console ou la procédure opérationnelle doit afficher l’état global et celui de chaque étape, la dernière erreur classée, le nombre de tentatives, les références externes et l’action autorisée. Évitez de proposer un bouton générique « tout réessayer ». Présentez des options limitées : réessayer une étape idempotente, consulter l’état distant, exécuter une compensation ou faire remonter le cas.

Protégez ces actions par des autorisations basées sur les rôles ; exigez une confirmation supplémentaire pour les effets sensibles et consignez qui a agi, quand, quel choix a été fait et pourquoi. Si la réexécution modifie les données d’entrée, imposez la création d’une nouvelle exécution ou d’une révision explicite au lieu de modifier silencieusement l’entrée d’un processus historique.

Pour diagnostiquer sans exposer d’informations sensibles, conservez les identifiants de corrélation, les codes d’erreur, la version du processus et les références nécessaires à la consultation des systèmes sources. Masquez les jetons, les données personnelles et les charges utiles complètes. Définissez également la durée de conservation des enregistrements et les personnes autorisées à les consulter. Une trace utile explique ce qui s’est passé sans devenir une copie superflue des données métier.

Tester les défaillances et déployer progressivement la récupération

Testez les interruptions à des points précis : avant l’exécution d’une étape, après l’action du fournisseur mais avant l’enregistrement de la réponse, pendant une compensation et lorsque deux workers tentent de prendre en charge le même processus. Vérifiez que l’état reste cohérent dans chaque cas, que les effets ne sont pas dupliqués et que toute action manuelle fait l’objet d’un audit.

Prévoyez des tests portant sur les réponses ambiguës, les clés d’idempotence répétées, les données invalides, les limites de nouvelles tentatives et les changements de version du flux. Les tests d’intégration avec des dépendances simulées peuvent reproduire des défaillances contrôlées ; lorsque le fournisseur réel a un comportement différent, vérifiez également le contrat et les mécanismes de consultation dans un environnement adapté.

Pour un flux existant, commencez par classer ses étapes selon leur réversibilité et leur idempotence. Persistez ensuite l’état d’une étape limitée, implémentez la récupération pour les défaillances les plus risquées et observez les cas en attente avant d’élargir le périmètre. N’effacez pas et ne réinitialisez pas les enregistrements historiques pour faciliter le déploiement : préservez la traçabilité et définissez comment interpréter les processus créés avec des versions antérieures.

Liste de vérification pour mettre en œuvre la récupération

Liste de vérification pour mettre en œuvre la récupération — guía visual de DedicatedPHP
  • Chaque étape a-t-elle des entrées identifiables, un état persisté et un résultat vérifiable ?
  • Sait-on quels appels sont idempotents et quoi faire lorsque leur résultat est ambigu ?
  • Existe-t-il des limites de tentatives, des délais et une classification des erreurs ?
  • Les compensations sont-elles définies comme des actions métier, avec un audit et un responsable ?
  • Les équipes opérationnelles peuvent-elles consulter les informations et agir avec les permissions appropriées, sans accéder à des données inutiles ?
  • Les défaillances entre les étapes, la concurrence, les réexécutions et les échecs de compensation ont-ils été testés ?
  • Existe-t-il une procédure d’escalade lorsqu’une reprise automatique n’est pas sûre ?

Le principe pratique consiste à conserver suffisamment de preuves pour décider de l’étape suivante et à arrêter l’automatisation lorsque ces preuves sont insuffisantes. Une récupération sûre ne cherche pas à masquer l’échec : elle explicite ce qui a été terminé, ce qui reste en attente et qui peut résoudre la situation.

Vous souhaitez appliquer ces idées à votre projet ?Parlons de votre plateforme PHP.
Afficher les services associés