Skip to content

Cron Jobs

akshat edited this page Sep 18, 2024 · 2 revisions

For jobs to be performed recurringly at a fixed interval, Goose provides Cron Jobs (aka Periodic Jobs): perform-every

Difference between Cron & one-off Jobs

Cron Job is different from Async/Scheduled jobs in following ways:

perform-every perform-async,perform-at,perform-in-sec
Recommended to call during app start-up Typically called as part of an API
Registers a Cron-Entry. A Job gets created when cron-schedule is due Creates/Schedules a Job for execution
Uniquely identified by String: cron-name Uniquely identified by UUID: id
Idempotent. Multiple app-servers may call it with the same effect Not idempotent
args/cron-schedule can be updated by calling perform-every with same cron-name args/schedule cannot be updated

Once a Cron Job is due for execution, it is enqueued & executed. In case of a failure, a Cron Job is retried like any normal Job. That means, there might be of more than 1 Cron Jobs running at same time with same args if delayed retry-time coincides with cron-schedule time. You can configure either the function logic or :retry-opts to avoid this scenario.

Timezone

By default, Goose uses System timezone to determine next runtime based on the cron expression. Many-a-times, Goose workers might be running in a different timezone than application users. Cron Jobs have a provision for :timezone so that cron expressions can be written in user's timezones without addition/subtraction of time.

;;; Acceptable timezone values
(java.time.ZoneId/getAvailableZoneIds)

Limitations

  • The most frequently a job can be scheduled with the crontab format is every minute.
    • If you want to run jobs more frequently, say every 20 seconds, you can do that via a meta cron job that runs every minute & schedules jobs to run in 20, 40, 60 seconds
  • If Goose workers are offline for a long time, Cron Jobs due for execution for that duration will be skipped. When a worker comes back online, it will backfill only 1 Job, instead of n missed Jobs
    • Cron Jobs must be resilient to skipped executions. We recommend keeping them cron-schedule agnostic. Instead of processing data for last 1 unit, it must handle last n unprocessed units
  • Cron Jobs args are static & defined at time of registration. They can be updated by re-registering
    • However, at runtime, the arguments will be static
    • To have Dynamic Args per execution, function must have logic to fetch them

Usage

(ns cron-jobs
  (:require [goose.client :as c]))

(let [name "my-cron-job"
      cron-schedule "*/5 * * * *" ; Runs every 5 mins.
      timezone "US/Pacific" ; Defaults to System timezone if not mentioned.
      cron-opts {:cron-name     name
                 :cron-schedule cron-schedule
                 :timezone      timezone}]
  (c/perform-every client-opts cron-opts `my-recurring-fn :static "arg"))

Previous: Batch Jobs        Next: Error Handling & Retries

Clone this wiki locally