17 déc. 2025·8 min de lecture

Corriger les conditions de course : arrêter les bugs asynchrones instables dans votre application

Apprenez à corriger les conditions de course : repérer le comportement non déterministe dans les files, les requêtes web et les mises à jour d'état, puis le stabiliser.

Corriger les conditions de course : arrêter les bugs asynchrones instables dans votre application

À quoi ressemblent les bugs asynchrones intermittents dans la vraie vie

Un bug asynchrone intermittent se produit quand vous faites deux fois la même chose et obtenez deux résultats différents. Vous cliquez sur le même bouton, envoyez le même formulaire ou lancez la même tâche, mais le résultat change. Une fois ça marche, la suivante échoue, ou ça marche à moitié et laisse les données dans un état étrange.

Le travail asynchrone augmente la probabilité car les tâches ne se terminent pas dans un ordre clair. Requêtes, jobs en file, timers et écritures en base peuvent se chevaucher. L'ordre peut changer selon de petites différences de timing : latences réseau, une requête DB lente, une reprise, ou un utilisateur qui refait la même action.

C'est pour ça que les conditions de course donnent souvent l'impression d'être « aléatoires ». Le bug est réel, mais il n'apparaît que lorsque deux choses se produisent dans le mauvais ordre. Par exemple :

  • Un utilisateur double-clique sur « Payer » et deux requêtes créent deux commandes.
  • Un job en arrière-plan redémarre après un timeout, alors que la première tentative avait en réalité réussi.
  • Deux onglets mettent à jour le même profil, et la dernière réponse écrase des données plus récentes.
  • Un webhook arrive avant que l'enregistrement dont il dépend soit commité.

Vous n'avez pas besoin d'être expert pour diagnostiquer ça. Si vous pouvez répondre « qu'est-ce qui s'est passé en premier ? » vous faites déjà le bon type de raisonnement. L'objectif est d'arrêter de deviner et de commencer à observer : quelles actions se sont exécutées, dans quel ordre, et ce que chacune pensait être l'état courant à ce moment.

Où les conditions de course se cachent généralement

Elles ne se trouvent que rarement sur la ligne évidente de code que vous regardez. Elles se cachent dans les interstices entre les étapes : après un clic, avant qu'une reprise soit terminée, pendant qu'un job tourne encore. Si vous voulez corriger les conditions de course, commencez par cartographier chaque endroit où le travail peut se produire deux fois ou dans un ordre différent que prévu.

Un endroit courant est les files et les jobs en arrière-plan. Un événement peut devenir deux jobs (ou le même job est repris), et chacun fonctionne bien isolément. Ensemble ils créent des doublons, traitent dans le mauvais ordre, ou déclenchent une tempête de reprises qui rend le système aléatoire.

Les requêtes web sont une autre source classique. Les utilisateurs double-cliquent, les réseaux mobiles reprennent, les navigateurs gardent des onglets parallèles plus longtemps que prévu. Deux requêtes frappent le même endpoint, lisent le même état ancien, puis écrivent, et la dernière écriture l'emporte silencieusement.

Les mises à jour d'état sont plus subtiles. Vous pouvez avoir deux mises à jour valides, mais qui se heurtent. Une mise à jour tardive peut écraser une valeur plus récente parce qu'elle a commencé plus tôt, ou parce que le code suppose qu'il est le seul auteur.

Voici les endroits à vérifier en priorité :

  • Consommateurs de queues et workers pouvant s'exécuter concurremment
  • Jobs cron qui peuvent se chevaucher si un run est lent
  • Logique « reprendre en cas d'échec » qui n'est pas idempotente
  • Appels à des API tierces qui peuvent réussir partiellement avant d'expirer
  • Tout flux qui fait read-modify-write sans garde

Exemple : une app générée par IA envoie un « email de bienvenue » depuis une requête web, et aussi depuis un job en arrière-plan « au cas où ». Sous charge, les deux chemins se déclenchent, et vous avez parfois des doublons. Le bug n'est pas le code de l'email. C'est la règle manquante sur qui est autorisé à envoyer et combien de fois.

Signaux rapides qui pointent vers du non-déterminisme

Les bugs non déterministes ressemblent à de la malchance : une erreur 500 apparaît, vous rafraîchissez, et ça marche. Ce motif « disparaît au retry » est un des signes les plus clairs que vous avez affaire à du timing, pas à une seule ligne de code cassée.

Regardez ce qui arrive aux données. Si un enregistrement est parfois manquant, parfois dupliqué, ou parfois écrasé par une valeur plus ancienne, quelque chose met à jour la même chose depuis deux endroits. Souvent ça apparaît comme « paiement capturé deux fois », « email envoyé deux fois » ou « profil sauvegardé mais champs revenus en arrière ».

Les logs vous trahiront souvent, même quand le bug ne le fait pas. Si vous voyez la même action deux fois pour le même utilisateur et payload (deux runs de job, deux appels API, deux handlers de webhook), supposez concurrence ou reprises tant que l'inverse n'est pas prouvé.

Signaux rapides à surveiller

Ces patterns reviennent quand il faut corriger des conditions de course :

  • Des rapports de bug qui disent « je ne peux pas reproduire », surtout sur différents appareils ou réseaux
  • Des erreurs qui montent quand le trafic est plus élevé ou que la base de données est plus lente
  • Un workflow qui échoue seulement quand plusieurs onglets sont ouverts ou que l'utilisateur double-clique
  • Une file de jobs qui « parfois » traite hors ordre ou exécute des doublons après des reprises
  • Des tickets support qui s'accumulent autour de timeouts, reprises ou performances dégradées

Un exemple concret : deux requêtes de checkout arrivent proches (double-click + réponse lente). Les deux voient « inventaire disponible », les deux réservent, et une seule échoue ensuite. La reprise « corrige » ensuite, masquant le vrai problème.

Si vous avez hérité d'un prototype généré par IA, ces symptômes sont courants car les flux asynchrones sont souvent collés ensemble sans propriétaire clair. FixMyMess audite rapidement ces chemins en traçant chaque requête et run de job de bout en bout avant de toucher au code.

D'abord instrumenter : le logging minimal qui paye

Quand vous essayez de corriger des conditions de course en « attendant un peu » ou en ajoutant des sleeps, vous rendez souvent le bug plus difficile à voir. Quelques logs bien choisis diront ce qui se passe réellement, même quand l'échec est rare.

Commencez par donner à chaque action utilisateur ou run de job un correlation ID. Utilisez-le partout : la requête web, le job en file, et tout appel en aval. Quand quelqu'un rapporte « ça a échoué une fois », vous pouvez tirer un fil à travers tout le système au lieu de lire du bruit non lié.

Loggez le début et la fin de chaque étape importante, avec des timestamps. Restez sobre et cohérent pour pouvoir comparer des runs. Enregistrez aussi la ressource partagée touchée, comme l'ID de ligne en base, la clé de cache, l'adresse email ou le nom de fichier. La plupart des bugs asynchrones intermittents surviennent quand deux flux touchent la même chose dans un ordre différent.

Un ensemble minimal de logs qui paie :

  • correlation_id, user_id (ou session_id), et request_id/job_id
  • nom d'événement et nom d'étape (start, finish)
  • timestamp et durée
  • identifiants de ressource (row ID, cache key, filename)
  • retry_count et error_type (timeout vs validation vs conflict)

Rendez les logs sûrs. N'affichez jamais de secrets, tokens, mots de passe bruts ou données de carte complètes. Si vous devez confirmer « même valeur », loggez une empreinte courte (comme les 4 derniers caractères ou une version masquée).

Exemple : un utilisateur clique « Payer » deux fois. Avec des correlation IDs et des logs start/finish, vous verrez deux requêtes en compétition pour mettre à jour le même order_id, l'une reprenant après un timeout. C'est souvent à ce stade que des équipes font appel à FixMyMess : nous auditons le code et ajoutons la bonne instrumentation avant de toucher à la logique, pour que la cause réelle devienne évidente.

Créer une reproduction fiable sans deviner

Les bugs asynchrones intermittents semblent impossibles car ils disparaissent quand on les observe. La façon la plus rapide de corriger les conditions de course est d'arrêter de « tenter des choses » et de construire un cas d'échec répétable.

Commencez par choisir un flux qui échoue et écrivez la séquence attendue en mots simples. Gardez-la courte, par exemple : « L'utilisateur clique Payer -> la requête crée la commande -> le job réserve l'inventaire -> l'UI affiche succès. » Cela devient votre baseline de ce qui devrait arriver et de ce qui arrive réellement.

Rendez le bug plus facile à déclencher en augmentant la pression sur le timing et la concurrence. Ne comptez pas sur l'occurrence naturelle.

  • Forcez des actions parallèles : double-cliquez, ouvrez deux onglets, ou lancez deux workers contre la même file.
  • Ajoutez un délai volontaire à l'étape suspecte (avant une écriture, après une lecture, avant un appel API externe).
  • Ralentissez l'environnement : limitez le réseau, ajoutez de la latence DB, ou lancez la tâche en boucle serrée.
  • Réduisez la portée : reproduisez dans le handler ou job le plus petit que vous pouvez isoler.
  • Notez précisément les entrées et le réglage de timing pour que n'importe qui puisse relancer la repro.

Un exemple concret : un bouton « Créer Projet » fait parfois deux projets. Mettez un délai de 300ms juste avant l'insertion, puis cliquez deux fois rapidement ou soumettez depuis deux onglets. Si vous déclenchez des doublons 8 fois sur 10, vous avez quelque chose de reproductible.

Gardez un petit script de repro (même quelques étapes manuelles) et traitez-le comme un test : exécutez-le avant et après chaque changement. Si vous héritez d'une app générée par IA, des équipes comme FixMyMess commencent souvent par construire cette repro d'abord, car elle transforme une plainte vague en une défaillance mesurable.

Étape par étape : stabiliser le flux plutôt que chasser le timing

Quand vous essayez de corriger les conditions de course en « ajoutant un délai » ou « en attendant que ça se termine », le bug se déplace souvent ailleurs. L'objectif est de rendre le flux sûr même quand les choses arrivent deux fois, dans le désordre, ou en même temps.

Commencez par nommer la chose partagée qui peut être corrompue. C'est souvent une seule ligne (enregistrement utilisateur), un compteur (solde), ou une ressource limitée (inventaire). Si deux chemins peuvent la toucher en même temps, vous avez le vrai problème, pas le timing.

Une façon pratique de corriger les conditions de course est de choisir une stratégie de sécurité et de l'appliquer de manière cohérente :

  1. Cartographiez qui lit et qui écrit la ressource partagée (requête A, job B, webhook C).
  2. Décidez de la règle : sérialiser le travail (un à la fois), verrouiller la ressource, ou rendre l'opération sûre à répéter.
  3. Ajoutez une clé d'idempotence pour toute action susceptible d'être rejointe (double clic, retry réseau, redelivery de queue).
  4. Protégez les écritures avec une transaction ou une mise à jour conditionnelle pour ne pas perdre la modification de quelqu'un d'autre.
  5. Prouvez-le avec des tests de concurrence et des exécutions répétées, pas avec un simple « ça marche sur ma machine ».

Exemple : deux requêtes « Passer commande » arrivent simultanément. Sans protection, les deux lisent inventory=1, les deux soustraient, et vous expédiez deux articles. Avec l'idempotence, la seconde requête réutilise le résultat de la première. Avec une mise à jour conditionnelle (ne soustraire que si inventory vaut toujours 1) dans une transaction, une seule requête peut réussir.

Si vous avez hérité d'un code généré par IA, ces protections manquent souvent ou sont inconsistantes. FixMyMess commence typiquement par ajouter l'idempotence minimale et des règles d'écriture sûres, puis réexécute le même scénario des dizaines de fois jusqu'à ce que ça devienne ennuyeusement stable.

Files et jobs en arrière-plan : doublons, reprises, ordre

La plupart des queues délivrent les jobs au moins une fois. Cela signifie que le même job peut s'exécuter deux fois, ou après un job plus récent, même si vous n'avez cliqué qu'une seule fois. Si votre handler suppose qu'il est la seule exécution, vous obtenez des résultats étranges : double facturation, emails en double, ou un enregistrement qui bascule entre deux états.

L'approche la plus sûre est de rendre chaque job sûr à répéter. Pensez résultats finaux, pas tentatives. Un job doit pouvoir s'exécuter de nouveau et aboutir au même état final.

Un pattern pratique pour corriger les conditions de course dans le traitement en arrière-plan :

  • Ajoutez une clé d'idempotence (orderId, userId + action + date) et enregistrez « déjà traité » avant d'effectuer des effets de bord.
  • Enregistrez un statut clair du job (pending, running, done, failed) pour que les réexécutions puissent sortir tôt.
  • Traitez les appels externes (paiement, email, upload) comme des étapes « faire une fois » avec leurs propres vérifications de dédupli.
  • Protégez-vous contre les événements hors-ordre en utilisant un numéro de version ou un timestamp, et ignorez les mises à jour plus anciennes.
  • Séparez les échecs retryables (timeouts, limites de taux) des non-retryables (mauvais input), et arrêtez de reprendre quand ça ne réussira jamais.

Les problèmes d'ordre sont faciles à rater. Exemple : un job « annuler abonnement » s'exécute, puis un job différé « renouveler abonnement » arrive et réactive l'utilisateur. Si vous stockez une version monotone (ou updatedAt) avec chaque changement d'abonnement, le handler peut rejeter les messages obsolètes et garder la vérité la plus récente.

Méfiez-vous des locks globaux. Ils peuvent masquer le bug en ralentissant tout, puis vous nuire en production en bloquant des travaux non liés. Préférez des verrous par entité (un utilisateur ou une commande à la fois) ou des vérifications d'idempotence.

Si vous avez hérité d'un worker IA qui duplique aléatoirement le travail, des équipes comme FixMyMess commencent souvent par ajouter l'idempotence et des vérifications d'« événement obsolète ». Ces deux changements transforment généralement un comportement instable en résultats prévisibles rapidement.

Requêtes web : double-clics, reprises et sessions parallèles

La plupart des bugs de requêtes surviennent quand la même action est envoyée deux fois, ou quand deux actions arrivent dans le « mauvais » ordre. Les utilisateurs double-cliquent, les navigateurs reprennent sur un réseau lent, les apps mobiles renvoient après un timeout, et plusieurs onglets se comportent comme des personnes distinctes.

Pour corriger les conditions de course ici, supposez que le client peut et enverra des doublons. Le serveur doit être correct même si l'UI se trompe, est lente, ou est hors ligne un moment.

Rendre les endpoints « faire la chose » sûrs à répéter

Si une requête peut créer des effets de bord (prélever une carte, créer une commande, envoyer un email), rendez-la idempotente. Une approche simple est une clé d'idempotence par action. Stockez-la avec le résultat, et si la même clé revient, renvoyez le même résultat.

Surveillez aussi les timeouts. Un échec classique : le serveur est encore en train de traiter, le client timeoute, puis réessaie. Sans déduplication, vous obtenez deux commandes, deux emails de reset, ou deux « bienvenue ».

Voici un ensemble rapide de protections qui paient généralement :

  • Exiger une clé d'idempotence pour les endpoints create/submit, et dédupliquer sur (user, key)
  • Utiliser des réponses d'erreur cohérentes pour que les clients n'essaient de nouveau qu'en cas d'erreur sûre
  • Logger un request ID et la clé d'idempotence à chaque tentative
  • Effectuer les effets de bord après avoir persisté l'enregistrement « cette action a eu lieu »
  • Traiter « déjà fait » comme un succès, pas comme une erreur effrayante

Empêcher les requêtes parallèles d'écraser l'état

Les écrasements arrivent quand deux requêtes lisent le même état ancien, puis écrivent des mises à jour. Exemple : deux onglets mettent à jour un profil et la dernière écriture gagne, annulant silencieusement l'autre.

Privilégiez des vérifications côté serveur comme des numéros de version (verrou optimiste) ou des règles explicites comme « ne mettre à jour que si le statut est toujours PENDING ». Si vous héritez de handlers générés par IA qui font read-modify-write sans garde, c'est un endroit courant où FixMyMess voit des rapports utilisateurs aléatoires « parfois ça sauvegarde, parfois non ».

Mises à jour d'état : empêcher les écrasements et incohérences

Beaucoup de comportements intermittents ne viennent pas d'un queue ou du réseau. Ce sont deux parties de votre appli qui mettent à jour la même donnée dans des ordres différents selon les runs. Un jour une requête gagne, le lendemain l'autre.

Le problème classique est la mise à jour perdue : deux workers lisent la même valeur ancienne, calculent une nouvelle valeur, et la dernière écriture écrase la première. Exemple : deux appareils mettent à jour les réglages de notification d'un utilisateur. Les deux lisent « activé », l'un désactive, l'autre change la sonnerie, et l'enregistrement final perd une modification.

Quand c'est possible, préférez les opérations atomiques plutôt que lire puis écrire. Les bases de données offrent souvent des primitives sûres comme increment, compare-and-set, et « update where version = X ». Cela transforme le timing en une règle claire : une seule mise à jour peut réussir, et le perdant retente avec des données fraîches.

Une autre solution est de valider les transitions d'état. Si une commande ne peut aller que de pending -> paid -> shipped, rejetez shipped -> paid même si ça arrive en retard. Cela empêche des requêtes tardives, reprises ou jobs d'inverser l'état.

Le cache peut aggraver le problème. Une lecture périmée du cache peut déclencher une écriture « correcte » basée sur des données anciennes. Si vous mettez en cache un état qui conduit à des écritures, assurez-vous de vider le cache lors des mises à jour ou de lire la source de vérité juste avant d'écrire.

Une façon simple de corriger les conditions de course est la propriété : décidez d'un seul endroit autorisé à mettre à jour une donnée, et faites transiter tous les changements par là. De bonnes règles de propriété ressemblent à :

  • Un service possède l'écriture, les autres demandent des changements
  • Une table ou un document est la source de vérité
  • Les mises à jour incluent un numéro de version (ou un timestamp) et sont rejetées si elles sont périmées
  • Seules les transitions d'état autorisées sont acceptées

Chez FixMyMess, nous voyons souvent des apps générées par IA mettre à jour le même enregistrement depuis le code UI, des handlers API et des jobs en arrière-plan. Rendre la propriété explicite est souvent le moyen le plus rapide d'arrêter les données incohérentes.

Pièges courants qui maintiennent les bugs intermittents

La façon la plus rapide de perdre une semaine sur ces bugs est de « traiter l'horloge » au lieu de la cause. Si le bug dépend du timing, vous pouvez le faire disparaître un jour et le laisser passer à l'étape suivante.

Une erreur fréquente est d'ajouter plus de reprises sans avoir d'idempotence. Si un job de paiement échoue à mi-chemin et reprend, vous pouvez facturer deux fois. Les retries sont sûrs seulement si chaque tentative peut être relancée sans changer le résultat.

Un autre piège est de disperser des délais aléatoires pour « espacer » les collisions. Ça masque souvent le problème en staging, puis empire en production car les patterns de charge changent. Les délais rendent aussi le système plus lent et plus difficile à raisonner.

Les gros locks peuvent aussi se retourner contre vous. Un mutex géant autour de « tout le flux » peut stopper la floculation, mais créer un nouveau mode de défaillance : longues attentes, timeouts et reprises en cascade qui réintroduisent le bug autrement.

Surveillez ces patterns qui entretiennent le non-déterminisme :

  • Traiter chaque échec comme retryable (timeouts, erreurs de validation, auth et conflits demandent des traitements différents)
  • Déclarer victoire parce que ça a passé localement une fois (la vraie concurrence n'apparaît pas souvent sur un laptop calme)
  • Logger juste « erreur arrivée » sans request/job id, numéro de tentative ou version d'état
  • Corriger des symptômes dans une couche alors que la course existe en dessous (UI, API et worker peuvent se chevaucher)
  • Hacks « temporaires » qui deviennent permanents (retries en plus, sleeps, ou blocs catch-all)

Si vous avez hérité d'une base de code IA avec ces pansements, un audit ciblé peut montrer rapidement où les retries, locks et l'absence d'idempotence masquent la vraie course. À ce stade, une réparation ciblée bat le tâtonnement.

Checklist rapide avant de déployer le correctif

Avant de déclarer mission accomplie, assurez-vous de ne pas simplement « gagner à la loterie du timing ». L'objectif est que les mêmes entrées donnent les mêmes résultats à chaque fois.

Voici une checklist pré-déploiement qui attrape la plupart des coupables :

  • Exécutez deux fois exprès. Déclenchez la même action deux fois (double click, deux workers, deux onglets) et confirmez que le résultat est toujours correct, pas juste « pas cassé ».
  • Cherchez la chose partagée. Identifiez la ressource partagée (ligne, fichier, clé de cache, solde, boîte de réception) et décidez comment elle est protégée : transaction, verrou, contrainte unique, ou mise à jour conditionnelle.
  • Auditez les retries pour les effets de bord. Si une reprise entraîne l'envoi d'un autre email, une nouvelle facturation ou l'écriture d'une ligne en double, ajoutez l'idempotence pour que « même requête » = « même effet ».
  • Comparez l'ordre dans les logs. Dans un run bon vs mauvais, les événements arrivent-ils dans un ordre différent (job démarré avant que l'enregistrement n'existe, callback avant que l'état soit sauvé) ? Les différences d'ordre indiquent souvent que vous avez corrigé un symptôme, pas la cause.
  • Privilégiez les garanties atomiques plutôt que les sleeps. Si une transaction, un index unique, ou un « update only if version matches » supprime le bug, c'est généralement plus sûr que d'ajouter des délais.

Exemple : si « Créer abonnement » facture parfois deux fois, vérifiez que l'appel au fournisseur de paiement est clefé par un token d'idempotence et que votre écriture DB est protégée par une contrainte unique sur ce token. Les doublons deviennent alors des opérations sans effet nocif plutôt qu'une urgence support.

Exemple : stabiliser un workflow intermittent de bout en bout

Imaginez un flux simple : deux collègues éditent le même client, et un job en arrière-plan met aussi à jour l'enregistrement après une importation. Tout semble bien en démo, mais avec de vrais utilisateurs vous voyez des résultats étranges.

Aujourd'hui, l'app utilise le « last write wins ». L'utilisateur A sauvegarde, puis B sauvegarde une seconde plus tard et écrase les changements d'A sans s'en apercevoir. Pendant ce temps, le job en file reprend après un timeout et envoie deux fois la notification « Client mis à jour ».

Pour confirmer que c'est non déterministe (et corriger la condition de course plutôt que deviner), créez une repro répétable :

  • Ouvrez l'enregistrement dans deux onglets (Onglet A et Onglet B)
  • Changez des champs différents dans chaque onglet
  • Cliquez sur sauvegarder dans les deux onglets en moins d'une seconde
  • Déclenchez le job en arrière-plan, puis forcez une reprise (par exemple en lançant temporairement une erreur après l'envoi)
  • Vérifiez l'état final de l'enregistrement et comptez les notifications

Si chaque exécution se termine différemment, vous avez trouvé le bug de timing.

La stabilisation prend généralement deux changements. D'abord, rendez les notifications idempotentes : ajoutez une clé d'idempotence comme customerId + eventType + version et enregistrez-la, pour que la même notification ne soit pas envoyée deux fois même si le job reprend.

Ensuite, rendez la mise à jour de l'enregistrement atomique. Encapsulez la mise à jour dans une transaction et ajoutez une vérification de version (optimistic locking). Si l'Onglet B essaie de sauvegarder une version ancienne, renvoyez un message clair « Cet enregistrement a changé, rafraîchissez et réessayez » au lieu d'écraser silencieusement.

Retestez la même repro 50 fois. Vous voulez des résultats identiques à chaque run : un état final explicable, et exactement une notification.

C'est le type de problème que FixMyMess voit souvent dans les apps générées par IA : des retries et du code asynchrone existent, mais les garde-fous (idempotence, verrous, transactions) manquent. Rendre ces protections explicites stabilise rapidement le système.

Prochaines étapes : rendre le système prévisible à nouveau

Choisissez les endroits où l'instabilité vous coûte le plus. Ne commencez pas par « toute l'app ». Commencez par 2-3 flux critiques où une mauvaise issue est coûteuse, par exemple : facturation, création de compte, passation de commande, envoi d'email, ou mise à jour d'inventaire.

Écrivez ces flux en étapes simples (quoi déclenche, ce que ça appelle, quelles données changent). Cette petite carte vous donne une « vérité » partagée quand les gens se disputent sur le timing. Elle facilite aussi la correction des conditions de course sans deviner.

Choisissez un garde-fou que vous pouvez déployer cette semaine. De petits changements suppriment souvent la majeure partie du risque :

  • Ajoutez une clé d'idempotence à l'action qui crée quelque chose (paiements, commandes, emails)
  • Utilisez une mise à jour conditionnelle (mettre à jour seulement si la version correspond, ou si le statut est toujours attendu)
  • Ajoutez une contrainte unique pour que les doublons échouent rapidement et en sécurité
  • Faites respecter l'ordre pour un topic de queue (ou regroupez plusieurs jobs en un job « état le plus récent »)
  • Mettez un timeout et une limite de reprises où les retries tournent actuellement indéfiniment

Si votre base de code a été générée par des outils IA et semble impossible à comprendre, planifiez un nettoyage ciblé : un flux, un propriétaire, et une semaine pour supprimer l'état partagé caché et les reprises « magiques ».

Exemple : si « Créer commande » envoie parfois deux emails de confirmation, rendez d'abord l'envoi d'email idempotent, puis durcissez le worker de queue pour qu'il puisse retrier sans changer le résultat.

Si vous voulez un plan clair et rapide, FixMyMess peut réaliser un audit gratuit du code pour repérer les conditions de course, les reprises et les écritures dangereuses. Et si vous avez besoin de stabilisation rapidement, nous pouvons diagnostiquer et réparer des prototypes générés par IA et les préparer pour la production en 48-72 heures avec une vérification experte.