Resumen

Puede ejecutar un Programador concurrentemente con el Servidor para manejar tareas periódicas. El Programador agregará periódicamente tareas a la cola, que luego serán ejecutadas por servidores trabajadores disponibles en el clúster.

Es necesario garantizar que solo se ejecute un Programador para cada programación para evitar tareas duplicadas. Utilizar un enfoque centralizado significa que no es necesario la sincronización y el servicio puede ejecutarse sin necesidad de bloqueos.

Si necesita agregar y eliminar dinámicamente tareas periódicas, use GestorDeTareasPeriódicas en lugar de usar directamente el Programador. Consulte esta wiki para obtener información más detallada.

Zona horaria

Por defecto, las tareas periódicas utilizan la hora UTC, pero puede utilizar SchedulerOpts para cambiar la zona horaria utilizada.

// Por ejemplo, use la zona horaria America/Los_Angeles en lugar de la zona horaria UTC por defecto.
loc, err := time.LoadLocation("America/Los_Angeles")
if err != nil {
    panic(err)
}
programador := asynq.NewScheduler(
    redisConnOpt, 
    &asynq.SchedulerOpts{
        Location: loc,
    },
)

Registro de tareas

Para agregar periódicamente tareas a la cola, debe registrar un registro de tarea con el Programador.

programador := asynq.NewScheduler(redisConnOpt, nil)

tarea := asynq.NewTask("ejemplo_tarea", nil)

// Puede utilizar una cadena de especificación de cron para especificar la programación.
entryID, err := programador.Register("* * * * *", tarea)
if err != nil {
    log.Fatal(err)
}
log.Printf("registrado una entrada: %q\n", entryID)

// También puede utilizar "@every " para especificar intervalos.
entryID, err = programador.Register("@every 30s", tarea)
if err != nil {
    log.Fatal(err)
}
log.Printf("registrado una entrada: %q\n", entryID)

// También puede pasar opciones.
entryID, err = programador.Register("@every 24h", tarea, asynq.Queue("micoa"))
if err != nil {
    log.Fatal(err)
}
log.Printf("registrado una entrada: %q\n", entryID)

Ejecutar el Programador

Para iniciar el Programador, llame a Run en el Programador.

programador := asynq.NewScheduler(redisConnOpt, nil)

// ... Registrar tareas

if err := programador.Run(); err != nil {
    log.Fatal(err)
}

Llamar a Run esperará la señal TERM o INT (por ejemplo, Ctrl-C).

Manejo de errores

Puede proporcionar una función controladora para manejar errores si el Programador no puede encolar tareas.

func handleEnqueueError(tarea *asynq.Task, opts []asynq.Option, err error) {
    // Su lógica de manejo de errores
}

programador := asynq.NewScheduler(
    redisConnOpt, 
    &asynq.SchedulerOpts{
        EnqueueErrorHandler: handleEnqueueError,
    },
)

Verificación a través de la CLI

La CLI tiene un subcomando llamado cron para verificar los registros del Programador.

Para ver todos los registros del Programador en ejecución actualmente, puede ejecutar el siguiente comando:

asynq cron ls

Este comando imprimirá una lista que contiene la ID, especificación de programación, próximo tiempo de encolado y último tiempo de encolado para cada registro.

También puede ejecutar el siguiente comando para ver el historial de cada registro:

asynq cron history