Borne les tentatives de livraison des webhooks et limite les alertes d'échec - #1739
Conversation
Les livraisons échouées étaient rejouées indéfiniment, sans distinguer « en cours de réessai » de « définitivement perdu ». Elles sont désormais bornées à 10 tentatives, et la dernière est marquée `abandoned_at` avec un message Sentry dédié. Les erreurs réseau Faraday, jusqu’ici remontées brutes, deviennent des tentatives sans code HTTP et suivent la même borne. WebhookHttpService reçoit des timeouts explicites.
L’alerte partait à la 5e exécution de chaque job : un incident touchant plusieurs demandes déclenchait autant d’emails que de livraisons en échec. Une seule alerte est désormais envoyée par webhook et par fenêtre de 2 heures (WEBHOOK_FAILURE_ALERT_THROTTLE_HOURS), réservée sous verrou pessimiste pour tenir face aux jobs concurrents.
Une livraison abandonnée s’affichait comme un simple « Échec » : impossible de savoir si DataPass allait retenter. L’écran distingue maintenant Succès, Échec et Abandonné, via un partial `_result_badge` partagé entre la liste et le détail. `abandoned_at` est également exposé sur l’API v1 et dans l’OpenAPI. - Mise à jour de la doc et du tutoriel
Les seeds ne produisaient que des succès et des échecs : vérifier le rendu d’un abandon demandait de manipuler la base à la main. Un webhook API Entreprise de prévisualisation porte les six états utiles de l’écran, recréés à chaque exécution des seeds sans doublon. Accès : /local-sign-in?email=api-entreprise@yopmail.com
46a89ec to
72443a8
Compare
|
Vu la régression que vous introduisez (si j'ai bien compris au bout de 4h vous passez un event en abandonné non rejouable ?) il faut que l'on itère coté API E/P pour gérer la potentielle perte de données. 4h c'est très très court (genre le site tombe la nuit on perd de l'info). On est très rapide pour fixer chez nous (< 24h généralement), une administration on peut tabler sur une bonne semaine -> de ce fait, tous les webhooks "perdus" font que le système perd un intérêt majeur : sa résilience. question: pourquoi introduire cette régression produit ? je ne sais pas exactement ce que vous voulez résoudre comme problème (le ticket est monstrueusement gros et il n'y a pas de btw
c'est faux non ? |
Merci pour le retour. la PR ne rend pas les événements abandonnés “non rejouables” et ne supprime pas le payload. Le “why” vient de l’incident de juillet, ou un développeur a reçu plusieurs centaines d’emails liés aux webhooks en échec/retry durant une nuit. L’objectif est donc de borner les retries automatiques et les alertes pour éviter une boucle infinie et du bruit opérationnel, pas de perdre de la donnée. Après effectivement, on peut revoir la fenêtre de temps / nombre de retry avant d'abandonnée / arrêter les retry. Le comportement cible côté produit est : historique conservé, payload conservé, rejeu possible, mais retries automatiques bornés. D'ailleurs si tu as d'autres idées je suis preneuse. |
Ok j'avais cru comprendre au milieu du ticket que le bouton rejouable était omis sur les cas abandonnés. Après cliquer sur 12883218936 payloads en défaut à la main c'est pas non plus la folie 😅
Je suis étonné de ce comportement, on a eu historiquement l'API E/P qui a planté plusieurs fois sur les webhooks de manière continue et on ne recevait qu'un email à chaque fois 🤔 Donc en gros c'est l'envoi d'email le souci, du coup ici il suffit juste de n'envoyer qu'un email par tranche de X heures, ce qui est cantonne le fix à quelques lignes (avec un compteur redis) vs ce que tu proposes qui in-fine fait pas mal de lignes. |
Ce que ça change
Aujourd'hui, un webhook dont l'endpoint ne répond plus est rejoué indéfiniment, et un endpoint injoignable ne laisse aucune trace dans l'historique. Cette PR :
abandoned_atdans l'API et affiche un badge « Abandonné » dans l'historique des appels.Comment tester
1. L'écran des tentatives (le plus rapide)
Se connecter comme développeur API Entreprise :
http://localhost:3000/local-sign-in?email=api-entreprise@yopmail.com
Aller dans Développeurs > Webhooks, puis « Voir les appels » sur le webhook
http://localhost:3000/dummy/failing/webhooks.Les seeds créent 6 tentatives qui couvrent tous les états de l'écran :
Cliquer sur une tentative abandonnée : le détail affiche le même badge, le payload envoyé et la réponse reçue.
2. Les tests automatisés
Ils couvrent les comportements qui ne se voient pas à l'écran : arrêt des relances après la 10ᵉ tentative, marquage de l'abandon, message Sentry distinct, endpoint injoignable et timeout enregistrés avec un statut vide, envoi unique de l'alerte sous charge concurrente, et remise à zéro de la limite quand l'endpoint se rétablit.
3. En recette, sur sandbox
La branche n'est pas mergée, donc seul sandbox peut la prendre : staging et production déploient toujours
main.Il faut ensuite un endpoint qui accepte d'abord les appels, puis tombe en panne : DataPass teste l'URL au moment de l'activation et refuse un webhook dont l'endpoint ne répond pas 2xx. https://webhook.site fait exactement ça — il fournit une URL jetable qui répond 200, et son bouton « Edit » permet de basculer la réponse en 500 quand on veut.
Ce qu'on doit observer :
L'abandon arrive naturellement au bout d'environ 4 h. Pour le voir tout de suite, un compte admin peut relancer les jobs en attente depuis
/workersjusqu'à la 10ᵉ tentative : la dernière prend alors le badge « Abandonné », etGET /api/v1/webhooks/:id/attemptsrenvoieabandoned_at.Le cas « pas de réponse » demande un endpoint qui met plus de 10 secondes à répondre (délai de réponse réglable sur webhook.site, ou stub perso derrière un tunnel). Résultat attendu : une tentative affichée « Pas de réponse » au lieu d'un code HTTP.
Doc
docs/webhooks.mdet le tutoriel développeurs sont à jour : politique de retry, tableau des délais avec temps cumulé, abandon, limite de l'alerte.Points d'attention pour la relecture
attemptsvalaitexecutions + 1. C'est un alignement avec ce que la doc annonçait déjà.