¿Debe recuperarse una ejecución de cron perdida? grace_minutes responde trabajo por trabajo


Cierras el portátil para una reunión de dos horas. Cuando lo vuelves a abrir hay dos informes diarios idénticos esperando: el trabajo de las 15:00 perdió su franja mientras la máquina dormía, se recuperó al despertar y luego volvió a dispararse a las 16:00. Borras el duplicado y piensas “la próxima vez, que se salte”.

Solo que la recuperación existe por algo. Si la sincronización de datos de las 03:00 falló porque el equipo se reinició, quieres que se ejecute poco después del arranque, no mañana. La pregunta nunca fue si recuperar está bien; es cuánto tiempo está dispuesto a esperar un trabajo concreto. Antes Hermes aplicaba una sola regla a todos los trabajos. Ahora cada uno puede fijar la suya.

Qué hace realmente el comportamiento por defecto

El planificador detecta una hora de ejecución que ya pasó y tiene dos opciones: ejecutarla ahora, o saltarla y reanclarse a la siguiente ocurrencia. La decisión usa una ventana de recuperación:

  • la mitad del periodo del trabajo,
  • acotada entre 2 minutos y 2 horas.

Así, un trabajo que se ejecuta cada minuto tiene una ventana de 2 minutos: cualquier cosa posterior ya está obsoleta y salta al minuto siguiente en lugar de lanzar una ráfaga de ejecuciones de recuperación. Un trabajo diario dispone de 12 horas, de modo que reabrir el portátil a media mañana sigue contando como “tarde, pero válido”. Uno horario dispone de 30 minutos.

Periodo Ventana de recuperación por defecto
Cada minuto 2 minutos (suelo)
Cada 15 minutos 7.5 minutos
Cada hora 30 minutos
Diario 12 horas
Semanal 2 horas (techo)

Los trabajos de una sola ejecución van aparte: reciben una tolerancia de 120 segundos y después caducan.

La regla es razonable —los periodos largos toleran más retraso, los cortos avanzan rápido—, pero encaja mal en dos casos frecuentes:

  • Informes diarios o semanales que deben ejecutarse como máximo una vez al día. Una ventana de 12 horas hace que se dispare al despertar aunque ya hayas revisado los números en el móvil, así que recibes notificaciones duplicadas.
  • Trabajos sensibles al tiempo. Traer datos de mercado 30 minutos antes de la apertura no sirve de nada a las 11:00. Mejor saltarlo.

Sobrescribir la ventana en cada trabajo

La sobrescritura se expresa en minutos:

# nunca recuperar: una ocurrencia perdida se salta
hermes cron edit market-open --grace-minutes 0

# dispuesto a ejecutarse hasta tres horas tarde
hermes cron edit nightly-sync --grace-minutes 180

También puedes fijarlo al crearlo:

hermes cron create "30 9 * * 1-5" "Trae las cotizaciones previas a la apertura y redacta el informe" \
  --name market-open \
  --grace-minutes 5

El rango va de 0 a 1440 minutos (un día completo). 0 es un valor real y significa “no recuperar nunca”. Para volver a la ventana calculada, pasa una cadena vacía:

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

Solo se aplica a expresiones cron. Las programaciones once e interval no tienen una franja horaria perdida —interval cuenta desde la última ejecución y once es una hora absoluta—, así que fijarlo ahí no hace nada, y la CLI te lo dice en lugar de aceptarlo en silencio.

Tres configuraciones típicas

Informes diarios y semanales: 0. Te importa si se ejecutó hoy, no si la copia de ayer acaba apareciendo. Con 0 la ocurrencia perdida se salta, el salto queda en el log y la siguiente franja se ejecuta con normalidad. Se acaban las notificaciones duplicadas.

Trabajos nocturnos en una máquina que hiberna: ponlo alto. Quienes usan portátil son el caso clásico: una sincronización a las 23:00 y una máquina que arranca a las 08:00. La ventana por defecto cubre un trabajo diario, pero uno semanal está limitado a 2 horas, así que pon --grace-minutes 600 y seguirá recuperándose por la mañana.

Trabajos sensibles al tiempo: mantenlo pequeño. Los trabajos previos a la apertura, al lanzamiento o a la conciliación no valen nada tarde. Dales 5 o 10 minutos y deja que se salten. Un informe obsoleto que sale bien es más peligroso que un trabajo que no se ejecutó, porque nadie se da cuenta.

Desactivar la recuperación de forma global

Si no quieres recuperaciones en ningún sitio:

hermes config set cron.catch_up_missed false

Un trabajo recurrente que ya pasó su ventana se reancla entonces a su siguiente ocurrencia futura en lugar de dispararse, y el salto queda registrado. Los trabajos que aún están dentro de la ventana, más los disparos manuales, se comportan con normalidad. Respecto al ajuste por trabajo: el interruptor global es un apagado, y el valor por trabajo relaja o estrecha la ventana de un trabajo. Una vez que la recuperación está apagada globalmente, una ventana generosa por trabajo no tiene sobre qué actuar.

En despliegues alojados con un provider de cron gestionado hay una capa más: cron.misfire_grace_minutes (10 por defecto) es cuánto espera el gateway al reintento del propio provider antes de recuperar en local, de modo que un traspaso fallido cuesta minutos en lugar de todo el día.

Cuatro trampas

  • 0 es un valor, no “sin fijar”. Los comentarios del código lo señalan expresamente: 0 == False, así que cualquier comprobación del tipo “vacío significa bórralo” descarta 0 en silencio y restaura la ventana por defecto. La CLI y el parseo de configuración tratan un 0 explícito como fijado; si editas jobs.json con un script, ten el mismo cuidado.
  • Solo expresiones cron. Las programaciones interval y once lo ignoran; no controlará cómo se recupera un trabajo “cada 5 minutos”.
  • La distribución de perfiles descarta campos desconocidos. Si exportas y distribuyes definiciones de trabajos entre perfiles, grace_minutes debe seguir en la lista de campos permitidos, o el lado receptor vuelve a la ventana por defecto.
  • Las comprobaciones de salud se mueven con él. La línea “este trabajo está atrasado” del panel usa la misma ventana que el planificador. Cambiar la tolerancia cambia también el umbral de alarma, lo cual es correcto (si no, el panel señalaría trabajos que el planificador considera puntuales), pero el momento de tus alertas se desplazará.

Confirmar que ha surtido efecto

hermes cron list                 # la fila Grace solo aparece cuando hay una sobrescritura fijada
hermes cron doctor               # señala un valor inutilizable, o uno fijado en una programación que no es cron

En hermes cron list, el bloque de detalle de cada trabajo gana una fila Grace que muestra algo como 180 min. Los trabajos sin sobrescritura no tienen esa fila. hermes cron doctor revisa dos modos de fallo: un valor inutilizable y un valor fijado en una programación que no puede usarlo. Para confirmar que un salto ocurrió de verdad, busca la línea de log Skipping missed occurrence: indica la causa (grace_minutes o el cron.catch_up_missed=false global) y la hora de la siguiente ejecución.

Para un recorrido completo de comprobación de salud, mira la guía de cron doctor; para los disparos fallidos por zonas horarias, el artículo sobre zonas horarias y horario de verano; y para crear trabajos desde cero, la guía de automatización con cron.

Estado

grace_minutes llegó a main el 2026-10-28 y ya viaja en la v0.22.6 (2026-11-02): con actualizar basta para tener ventana de recuperación por tarea. En compilaciones anteriores, el recurso disponible es el interruptor global cron.catch_up_missed: una talla única, pero suficiente para detener las recuperaciones duplicadas.