scheduler

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 7, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Overview

Package scheduler runs recurring work on a cron expression or a fixed interval, with the two properties that decide whether scheduled work is safe to deploy on more than one replica.

Singleton   one replica runs the job, not all of them.
Overlap     a slow run does not start a second copy of itself.

Both failure modes are invisible in development, where there is one replica and every job finishes in a millisecond. In production they are how a nightly billing sweep charges three times, and how a reconciler that normally takes 20 seconds piles up 200 copies the night it takes 20 minutes.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Job

type Job struct {
	// Name identifies the job in logs and is the lock key. Required, unique.
	Name string
	// Cron is a standard 5-field expression ("0 3 * * *"). Set this or Every.
	//
	// Descriptors are supported: @hourly, @daily, @weekly, @every 1h30m.
	Cron string
	// Every runs at a fixed interval from start-up. Set this or Cron.
	Every time.Duration
	// Run does the work. It MUST honour ctx — a job that ignores its deadline
	// cannot be stopped, and shutdown will wait for it until the drain
	// timeout and then abandon it mid-write.
	Run func(ctx context.Context) error

	// Singleton makes exactly one replica run each occurrence, via the
	// scheduler's Locker. Leave it off ONLY for work that is safe to run N
	// times — a cache warm, a metric refresh.
	Singleton bool
	// LockTTL must exceed the job's worst-case runtime. Too short and the
	// lock expires mid-run, letting a second replica start: the exact thing
	// Singleton was for. Defaults to Timeout, or 5 minutes.
	LockTTL time.Duration
	// Timeout bounds one run. Defaults to 5 minutes; zero is not unlimited,
	// because an unbounded scheduled job is how a connection pool is
	// exhausted overnight.
	Timeout time.Duration
	// RunOnStart fires once at start-up, in addition to the schedule.
	RunOnStart bool
	// Jitter spreads the start across replicas by up to this much. With
	// Singleton it avoids a thundering herd on the lock; without it, it
	// avoids every replica hitting the database on the same second.
	Jitter time.Duration
}

Job is one recurring task.

type Scheduler

type Scheduler struct {
	// contains filtered or unexported fields
}

Scheduler owns the running jobs. Register it as a lifecycle hook: it starts in OnReady and drains in OnShutdown.

func New

func New(locker lock.Locker) *Scheduler

New builds a scheduler. Pass a lock.Locker for Singleton jobs; without one, Singleton jobs are refused at Add rather than silently running everywhere.

func (*Scheduler) Add

func (s *Scheduler) Add(j Job) error

Add registers a job. It validates eagerly, so a malformed cron expression fails the boot instead of being discovered the night it was supposed to run.

func (*Scheduler) Jobs

func (s *Scheduler) Jobs() []string

Jobs lists the registered job names.

func (*Scheduler) MustAdd

func (s *Scheduler) MustAdd(j Job)

MustAdd is Add, panicking on an invalid job. Jobs are declared in code at boot, so a panic there is the right failure.

func (*Scheduler) OnReady

func (s *Scheduler) OnReady(ctx context.Context) error

OnReady implements lifecycle.Ready: it starts every job.

Ready rather than Init on purpose — a reconciler that starts before the listener races the boot it is part of, and will happily run against half-constructed dependencies.

func (*Scheduler) OnShutdown

func (s *Scheduler) OnShutdown(ctx context.Context) error

OnShutdown implements lifecycle.Shutdowner: stop scheduling and wait for the runs in flight, up to the drain deadline.

func (*Scheduler) Start

func (s *Scheduler) Start(parent context.Context) error

Start begins running jobs. The context it derives from must outlive the jobs; pass the application context, not a request's.

func (*Scheduler) Stop

func (s *Scheduler) Stop(ctx context.Context) error

Stop halts scheduling and waits for running jobs.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL