Documentation

Core Concepts

This page describes the task model, schedule syntax, dependency policies, timeout handling, and lifecycle rules.

Task model

A scheduler task contains a schedule, an action, an optional description, an optional execution timeout, and an enabled flag. Add accepts either func() or func() error. Use func() error when the task participates in dependency handling or must report failures.

Each task receives a monotonically increasing int64 ID. List returns enabled tasks currently held by the scheduler heap. Remove disables one task by ID; RemoveAll clears all scheduled entries.

Cron schedules

The parser accepts exactly five fields in this order:

Field Range Meaning
Minute 0–59 Minute of the hour
Hour 0–23 Hour of the day
Day of month 1–31 Calendar day
Month 1–12 Month
Day of week 0–6 Sunday through Saturday

Each field supports a wildcard (*), a single value, a range (9-17), a comma-separated list (9,12,18), or a step (*/5). For example, */5 9-17 * * 1-5 runs every five minutes during weekday business hours.

Descriptors and intervals

The scheduler supports @yearly, @annually, @monthly, @weekly, @daily, @midnight, and @hourly. The @every <duration> form schedules a fixed interval, with a minimum interval of 30 seconds.

c.Add("@hourly", func() error { return nil })
c.Add("@every 5m", func() error { return refreshCache() })

Cron expressions search for the next matching minute. Fixed intervals calculate the next run by adding the configured duration to the current time.

Dependencies

Declare prerequisites by passing []core.Wait to Add:

parentID, _ := c.Add("@every 1m", func() error {
    return prepare()
})

_, err := c.Add("@every 1m", func() error {
    return process()
}, []core.Wait{{ID: parentID, Delay: 10 * time.Second, State: core.Stop}})

A dependent task waits until every prerequisite is completed. Wait.Delay controls how long the dependency worker waits; when it is zero, the worker uses one minute. Stop fails the dependent task if that prerequisite fails. Skip ignores the failed prerequisite and continues evaluating the remaining dependencies.

Timeouts and callbacks

Pass a time.Duration to set an execution timeout and a func() to receive the timeout callback:

c.Add("@every 1m", func() error {
    return slowJob()
}, 3*time.Second, func() {
    log.Println("task timed out")
})

A timeout marks the task as failed and invokes onDelay. Returned errors and panics also produce a failed task state. The scheduler records task start, end, duration, and error internally for dependency updates and logging.

Lifecycle and concurrency

Start starts the event loop and dependency workers and is safe to call repeatedly while already running. The scheduler uses a min-heap to wait only for the nearest next occurrence. Add and remove operations are sent through channels after startup so the loop can safely recalculate its timer.

Stop stops scheduling new occurrences and the dependency workers. It returns a context that is canceled after in-flight scheduler tasks have finished, allowing callers to wait for graceful shutdown.

State transitions

Tasks move through these states:

Pending -> Running -> Completed
                   \-> Failed

Recurring tasks are placed back into Pending for their next scheduled occurrence. Removing a task disables its heap entry and prevents future execution.

See Getting Started for a runnable example and API Reference for signatures.

中文