Une exécution cron manquée doit-elle rattraper son retard ? grace_minutes répond tâche par tâche


Vous refermez le portable pour une réunion de deux heures. À la réouverture, deux rapports quotidiens identiques vous attendent : la tâche de 15:00 a manqué son créneau pendant que la machine dormait, s’est rattrapée au réveil, puis a tiré de nouveau à 16:00. Vous supprimez le doublon en pensant « la prochaine fois, il suffira de l’ignorer ».

Sauf que le rattrapage existe pour une raison. Si la synchronisation de données de 03:00 a été manquée parce que la machine a redémarré, vous voulez qu’elle tourne peu après le démarrage, pas demain. La vraie question n’a jamais été de savoir si le rattrapage est une bonne chose, mais combien de temps une tâche donnée doit accepter d’attendre. Hermes appliquait autrefois une règle unique à toutes les tâches. Désormais chacune peut fixer la sienne.

Ce que fait réellement le comportement par défaut

Le planificateur trouve une échéance dans le passé et dispose de deux options : l’exécuter maintenant, ou l’ignorer et se recaler sur l’occurrence suivante. La décision repose sur une fenêtre de rattrapage :

  • la moitié de la période de la tâche,
  • bornée entre 2 minutes et 2 heures.

Une tâche qui tourne chaque minute dispose donc d’une fenêtre de 2 minutes : au-delà, l’échéance est périmée et elle saute à la minute suivante au lieu de déclencher une rafale de rattrapages. Une tâche quotidienne obtient 12 heures : rouvrir le portable en milieu de matinée compte encore comme « en retard mais valide ». Une tâche horaire obtient 30 minutes.

Période Fenêtre de rattrapage par défaut
Chaque minute 2 minutes (plancher)
Toutes les 15 minutes 7,5 minutes
Toutes les heures 30 minutes
Quotidienne 12 heures
Hebdomadaire 2 heures (plafond)

Les tâches ponctuelles sont à part : elles bénéficient de 120 secondes de grâce, puis expirent.

La règle est sensée — les longues périodes tolèrent plus de retard, les courtes avancent rapidement — mais elle s’ajuste mal à deux cas fréquents :

  • Les rapports quotidiens ou hebdomadaires qui ne doivent tourner qu’une fois par jour. Une fenêtre de 12 heures signifie qu’ils partent au réveil alors que vous avez déjà traité les chiffres sur votre téléphone : vous recevez des notifications en double.
  • Les tâches sensibles au timing. Récupérer des données de marché 30 minutes avant l’ouverture n’a aucun intérêt à 11:00. Mieux vaut ignorer.

Redéfinir la fenêtre tâche par tâche

La redéfinition s’exprime en minutes :

# jamais de rattrapage : une occurrence manquée est ignorée
hermes cron edit market-open --grace-minutes 0

# accepte de tourner jusqu'à trois heures en retard
hermes cron edit nightly-sync --grace-minutes 180

Vous pouvez aussi la fixer à la création :

hermes cron create "30 9 * * 1-5" "Récupère les cours avant l'ouverture et rédige le briefing" \
  --name market-open \
  --grace-minutes 5

La plage va de 0 à 1440 minutes (une journée entière). 0 est une vraie valeur qui signifie « jamais de rattrapage ». Pour revenir à la fenêtre calculée, passez une chaîne vide :

hermes cron edit nightly-sync --grace-minutes ""

Cela ne s’applique qu’aux expressions cron. Les planifications once et interval n’ont pas de créneau horaire manqué — interval compte depuis la dernière exécution, once est une heure absolue — donc la fixer n’y produit rien, et le CLI vous le signale au lieu de l’accepter en silence.

Trois réglages typiques

Rapports quotidiens et hebdomadaires : 0. Ce qui vous intéresse, c’est de savoir si la tâche a tourné aujourd’hui, pas si la copie d’hier finit par apparaître. Avec 0, l’occurrence manquée est ignorée, le saut est journalisé et le créneau suivant se déroule normalement. Les notifications en double cessent.

Tâches nocturnes sur une machine qui dort : mettez une grande valeur. Les utilisateurs de portable sont le cas classique : une synchronisation à 23:00, une machine qui démarre à 08:00. La fenêtre par défaut couvre une tâche quotidienne, mais une tâche hebdomadaire plafonne à 2 heures : réglez --grace-minutes 600 et elle se rattrape encore le matin.

Tâches sensibles au timing : gardez-la petite. Les tâches d’avant-ouverture, d’avant-lancement, d’avant-rapprochement ne valent rien en retard. Donnez-leur 5 ou 10 minutes et laissez-les sauter. Un rapport périmé qui réussit est plus dangereux qu’une tâche qui n’a pas tourné, parce que personne ne le remarque.

Désactiver le rattrapage globalement

Si vous ne voulez aucun rattrapage, où que ce soit :

hermes config set cron.catch_up_missed false

Une tâche récurrente au-delà de sa fenêtre est alors recalée sur sa prochaine occurrence future au lieu de se déclencher, et le saut est journalisé. Les tâches encore dans leur fenêtre, ainsi que les déclenchements manuels, se comportent normalement. Par rapport au réglage par tâche : l’interrupteur global est un coupe-circuit, la valeur par tâche assouplit ou resserre la fenêtre d’une tâche — une fois le rattrapage coupé globalement, une fenêtre généreuse n’a plus rien sur quoi agir.

Sur les déploiements hébergés avec un fournisseur cron géré, il existe une couche supplémentaire : cron.misfire_grace_minutes (10 par défaut) correspond au temps pendant lequel le gateway attend la nouvelle tentative du fournisseur avant de rattraper localement, si bien qu’un transfert raté coûte des minutes au lieu de la journée entière.

Quatre pièges

  • 0 est une valeur, pas « non défini ». Les commentaires du code le disent explicitement : 0 == False, donc tout test du type « vide signifie effacer » élimine silencieusement 0 et rétablit la fenêtre par défaut. Le CLI et l’analyse de configuration traitent un 0 explicite comme défini — si vous éditez jobs.json par script, soyez aussi prudent.
  • Expressions cron uniquement. Les planifications interval et once l’ignorent ; cela ne contrôlera pas le rattrapage d’une tâche « toutes les 5 minutes ».
  • La distribution de profils écarte les champs inconnus. Si vous exportez et distribuez des définitions de tâches entre profils, grace_minutes doit rester dans la liste des champs autorisés, sinon le destinataire retombe sur la fenêtre par défaut.
  • Les contrôles de santé suivent. La ligne « cette tâche est en retard » du tableau de bord utilise la même fenêtre que le planificateur. Modifier la grâce modifie aussi le seuil d’alerte — ce qui est correct (sinon le tableau de bord signalerait des tâches que le planificateur considère à l’heure), mais le calendrier de vos alertes va se décaler.

Vérifier que le réglage a pris effet

hermes cron list                 # la ligne Grace n'apparaît que si une redéfinition est définie
hermes cron doctor               # signale une valeur inutilisable, ou posée sur une planification non cron

Dans hermes cron list, le bloc de détail de chaque tâche gagne une ligne Grace affichant par exemple 180 min. Les tâches sans redéfinition n’ont pas cette ligne. hermes cron doctor contrôle deux modes de défaillance : une valeur inutilisable, et une valeur posée sur une planification qui ne peut pas s’en servir. Pour confirmer qu’un saut a bien eu lieu, cherchez la ligne de journal Skipping missed occurrence — elle nomme la cause (grace_minutes ou le global cron.catch_up_missed=false) et l’heure de la prochaine exécution.

Pour une procédure de contrôle de santé complète, voyez le guide cron doctor ; pour les déclenchements ratés dus aux fuseaux horaires, l’article sur les fuseaux et l’heure d’été ; pour construire des tâches de zéro, le guide d’automatisation cron.

État actuel

grace_minutes est arrivé sur main le 2026-10-28 et fait partie de la v0.22.6 (2026-11-02) : une mise à jour normale suffit pour régler le rattrapage tâche par tâche. Sur les versions antérieures, le contournement reste l’interrupteur global cron.catch_up_missed : taille unique, mais suffisant pour arrêter les rattrapages en double.