Documentation
¶
Overview ¶
Package schedule runs recurring tasks: functions, app commands and queue jobs, on cron expressions or helpers such as DailyAt.
s.Command("reports:send").DailyAt("08:00").WithoutOverlapping()
s.Job(jobs.PruneSessions{}).Hourly()
s.Func("ping", func(ctx context.Context) error { ... }).EveryFiveMinutes()
Run it in process with Work (vukem schedule:work) or from one cron entry calling RunDue every minute (vukem schedule:run). Schedule holds the Task list, Cron parses five-field expressions, and WithoutOverlapping takes a lock in the Options.Locks cache.
See https://github.com/AlexGalhardo/vukem/blob/main/docs/subsystems.md#scheduler.
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/AlexGalhardo/vukem/schedule"
)
func main() {
s := schedule.New(schedule.Options{})
s.Func("ping", func(context.Context) error { return nil }).EveryFiveMinutes()
s.Command("reports:send").DailyAt("08:00").WithoutOverlapping()
for _, t := range s.Tasks() {
fmt.Println(t.Name(), t.Expression())
}
now := time.Date(2026, 1, 5, 8, 0, 0, 0, time.UTC)
for _, t := range s.Due(now) {
fmt.Println("due at 08:00:", t.Name())
}
}
Output: ping */5 * * * * reports:send 0 8 * * * due at 08:00: ping due at 08:00: reports:send
Index ¶
- Variables
- type Cron
- type Options
- type Schedule
- func (s *Schedule) Command(name string, args ...string) *Task
- func (s *Schedule) Due(now time.Time) []*Task
- func (s *Schedule) Func(name string, fn func(ctx context.Context) error) *Task
- func (s *Schedule) Job(j queue.Job, opts ...queue.Option) *Task
- func (s *Schedule) Next(t *Task, now time.Time) time.Time
- func (s *Schedule) RunDue(ctx context.Context, now time.Time) error
- func (s *Schedule) Tasks() []*Task
- func (s *Schedule) Validate() error
- func (s *Schedule) Work(ctx context.Context, now func() time.Time) error
- type Task
- func (t *Task) Cron(expr string) *Task
- func (t *Task) Daily() *Task
- func (t *Task) DailyAt(hhmm string) *Task
- func (t *Task) Every(d time.Duration) *Task
- func (t *Task) EveryFiveMinutes() *Task
- func (t *Task) EveryMinute() *Task
- func (t *Task) Expression() string
- func (t *Task) Hourly() *Task
- func (t *Task) HourlyAt(minute int) *Task
- func (t *Task) In(loc *time.Location) *Task
- func (t *Task) MonthlyOn(day int, hhmm string) *Task
- func (t *Task) Name() string
- func (t *Task) OnOneServer() *Task
- func (t *Task) Weekdays() *Task
- func (t *Task) WeeklyOn(weekday time.Weekday, hhmm string) *Task
- func (t *Task) WithoutOverlapping(ttl ...time.Duration) *Task
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrCron = errors.New("schedule: invalid cron expression")
ErrCron reports an invalid expression.
"schedule: OnOneServer needs a lock store shared by the servers " +
"(CACHE_STORE=database, Redis, or a custom store implementing cache.Sharer)",
)
ErrLocksNotShared is returned for OnOneServer tasks when Options.Locks is not shared by the servers (cache.Shared is false): the memory cache, or a store that does not declare cache.Sharer.
Functions ¶
This section is empty.
Types ¶
type Cron ¶
type Cron struct {
// contains filtered or unexported fields
}
Cron is a parsed five-field cron expression (minute hour day-of-month month day-of-week) with the usual syntax: "*", "5", "1-5", "*/15", "10-50/10", lists ("1,15"), month and weekday names ("JAN", "MON"), and the macros @yearly, @monthly, @weekly, @daily, @hourly. As in Vixie cron, when both day fields are restricted a day matches either.
func MustParseCron ¶
MustParseCron is ParseCron that panics (for literals).
func ParseCron ¶
ParseCron parses expr.
Example ¶
package main
import (
"fmt"
"time"
"github.com/AlexGalhardo/vukem/schedule"
)
func main() {
c, err := schedule.ParseCron("30 9 * * 1-5")
if err != nil {
fmt.Println(err)
return
}
from := time.Date(2026, 1, 3, 12, 0, 0, 0, time.UTC) // a Saturday
fmt.Println(c.Next(from).Format(time.RFC1123))
}
Output: Mon, 05 Jan 2026 09:30:00 UTC
type Options ¶
type Options struct {
// Location is the default time zone of expressions (default UTC).
Location *time.Location
// Log receives task outcomes (default slog.Default()).
Log *slog.Logger
// Locks backs WithoutOverlapping (default an in-memory store, which
// only protects one process; use the database or Redis cache store
// when several servers run the schedule).
Locks *cache.Cache
// Namespace keeps the locks of WithoutOverlapping and OnOneServer apart
// when several apps share one lock store (app.Schedule passes the
// normalized APP_NAME). Empty keeps the keys of v0.24.0.
Namespace string
// Commands runs app commands for Command tasks.
Commands func(ctx context.Context, name string, args []string) error
// Queue dispatches Job tasks.
Queue func() (*queue.Queue, error)
// StopTimeout is how long Work waits for running tasks once its
// context is cancelled before cancelling theirs (default 30s). Tasks
// must honor ctx; one that ignores it still holds Work.
StopTimeout time.Duration
}
Options configure a Schedule.
type Schedule ¶
type Schedule struct {
// contains filtered or unexported fields
}
Schedule holds the tasks.
func (*Schedule) RunDue ¶
RunDue runs the tasks due at now concurrently and waits for them. Task errors are logged and joined into the result.
func (*Schedule) Validate ¶ added in v0.25.0
Validate reports configuration that cannot work: an OnOneServer task with a lock store that is not shared by the servers (cache.Shared).
type Task ¶
type Task struct {
// contains filtered or unexported fields
}
Task is a scheduled unit of work; configure it with the chained methods.
func (*Task) Cron ¶
Cron sets a cron expression; it panics on a bad expression, so mistakes surface at boot.
func (*Task) Every ¶
Every runs the task every d, aligned to the clock (d must be a whole number of minutes dividing an hour or a day, e.g. 5m, 15m, 2h). It panics on any other d.
func (*Task) EveryFiveMinutes ¶
EveryFiveMinutes runs the task every five minutes.
func (*Task) EveryMinute ¶
EveryMinute runs the task every minute.
func (*Task) Expression ¶
Expression returns the cron expression.
func (*Task) HourlyAt ¶
HourlyAt runs the task every hour at minute; it panics unless minute is in 0-59.
func (*Task) MonthlyOn ¶
MonthlyOn runs the task on day of the month at "HH:MM"; it panics on a malformed time or a day outside 1-31.
func (*Task) OnOneServer ¶ added in v0.25.0
OnOneServer runs each occurrence of the task on one server only: the first scheduler to take the occurrence's lock (task name and minute) in Options.Locks runs it, the others skip it. The lock store must be shared by the servers (cache.Shared: the database or Redis cache, or a wrapper that declares cache.Sharer or exposes Unwrap); with an in-process or undeclared store, where every server could run the task, Validate fails and the task refuses to run (fail closed).