robfig/cron

repository·master·Indexed 11 days ago

https://github.com/robfig/cron

A Go library for scheduling jobs using cron expressions. It provides a robust engine for managing recurring tasks with support for standard and Quartz cron spec formats, interval-based schedules via Every(), and extensible job execution chains for panic recovery and concurrency control.

Tokens
5.5K
Snippets
33
Records
39
Agent score
95%

What's inside robfig/cron

  1. Understand the supported Cron spec formats

    master

    The library supports two primary scheduling formats:

    1. Standard Cron: The default format (e.g., used by Linux cron). The first field is minute.
    2. Quartz Format: An opt-in format (commonly used in Java) that includes a seconds field. Note that the year field supported by Quartz is not supported by this library.
  2. Configure Cron using functional options

    master
    In v3, the Cron type is configured using functional options passed to cron.New(). You can no longer use ad-hoc setters like SetLocation or direct field assignments for configuration. All configuration (such as loggers or locations) should be provided during construction.
  3. Install and import cron v3

    master

    To use cron v3, download the specific tagged release using Go Modules and import it using the v3 path. This version requires Go 1.11 or later.

    go get github.com/robfig/cron/v3@v3.0.0
    import "github.com/robfig/cron/v3"
  4. How cron descriptors work

    master

    Descriptors are shorthand strings starting with @ that represent predefined schedules. If you use NewParser, you must include the Descriptor option to use them.

    Supported descriptors include:

    • @yearly, @annually
    • @monthly
    • @weekly
    • @daily, @midnight
    • @hourly
    • @every <duration> (e.g., @every 1h30m using Go's time.ParseDuration format)
  5. How Cron, Job, and Schedule interact

    master

    The cron package is built on three primary abstractions:

    1. Cron: The central engine. It manages a collection of Entry objects, tracks time, and triggers execution.
    2. Job: The unit of work. Any type implementing Run() can be a job. A simple func() can be converted to a Job using FuncJob.
    3. Schedule: The timing logic. It defines when a job should run by implementing Next(time.Time) time.Time.

    When a Schedule indicates it is time for a Job to run, the Cron instance executes the job (wrapped in a Chain for safety/logging) in a new goroutine.

  6. Configure a Cron instance using Options

    master

    The cron package uses the functional options pattern to configure a Cron instance during initialization. You can pass one or more Option functions to the constructor (typically New or NewSingleton) to modify default behaviors such as timezone, parsing rules, job wrappers, and logging.

    // Example of applying multiple options to a new Cron instance
    c := cron.New(
    	cron.WithLocation(time.Local),
    	cron.WithSeconds(),
    	cron.WithLogger(myLogger),
    )
  7. Use timezones in cron expressions

    master

    You can specify a timezone for a cron expression by prefixing it with TZ= or CRON_TZ=. The parser will load the location using time.LoadLocation.

    // Example using CRON_TZ
    sched, err := cron.ParseStandard("CRON_TZ=America/New_York 0 0 15 */3 *")
  8. Use JobWrappers and Chains to decorate jobs

    master

    A JobWrapper is a function that takes a Job and returns a new Job with added behavior. A Chain is a sequence of these wrappers used to apply cross-cutting concerns (like logging or synchronization) to jobs.

    When using NewChain(m1, m2, m3).Then(job), the wrappers are applied in reverse order of their declaration, meaning the first wrapper in the chain is the outermost one. The execution order is equivalent to m1(m2(m3(job))).

    // Example of creating a chain and applying it to a job
    chain := cron.NewChain(wrapper1, wrapper2)
    wrappedJob := chain.Then(myJob)
    
    // The wrappedJob will now execute with the behaviors of wrapper1 and wrapper2 applied.
  9. Configure cron spec parsing (Standard vs Quartz)

    master

    By default, cron v3 uses the standard cron spec format where the first field is minute. If you need to support the Quartz-compatible format (which includes a seconds field), you must configure the parser explicitly.

    Use cron.WithSeconds() for a required seconds field, or cron.WithParser with specific bitwise flags for an optional seconds field.

    // Seconds field, required
    cron.New(cron.WithSeconds())
    
    // Seconds field, optional
    cron.New(cron.WithParser(cron.NewParser(
    	cron.SecondOptional | cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow | cron.Descriptor,
    )))
  10. Implement panic recovery using JobWrappers

    master

    By default, cron v3 does not recover from panics in jobs. To enable panic recovery and configure a logger for these events, use the cron.WithChain option with cron.Recover(logger). You can use cron.DefaultLogger or your own implementation.

    cron.New(cron.WithChain(
      cron.Recover(logger),  // or use cron.DefaultLogger
    ))
  11. Configure logging with logr support

    master

    The library supports extensible, key/value logging via the logr interface. To enable verbose logging, use cron.WithLogger with a logger that does not discard Info logs. A convenience wrapper for *log.Logger is provided via cron.VerbosePrintfLogger.

    cron.New(
      cron.WithLogger(cron.VerbosePrintfLogger(logger)))
  12. Calculate the next execution time with SpecSchedule.Next

    master

    The SpecSchedule type represents a duty cycle based on a traditional crontab specification. You can use its Next method to determine when the schedule will next trigger after a given time.

    Behavioral details:

    • Timezone Handling: If SpecSchedule.Location is set, the calculation is performed in that timezone. If it is time.Local, it uses the timezone of the time provided. If it is nil, it defaults to the timezone of the time provided.
    • Granularity: The schedule operates with second-level granularity.
    • Limits: If no valid time can be found within five years of the provided time, the method returns a zero time.Time.
    • Return Value: The method returns the next activation time in the original timezone of the input time.Time object.
    func (s *SpecSchedule) Next(t time.Time) time.Time