Documentation
¶
Overview ¶
Package cron implements a cron spec parser and job runner.
Usage ¶
Callers may register Funcs to be invoked on a given schedule. Cron will run them in their own goroutines.
c := cron.New()
c.AddFunc("0 30 * * * *", func() { fmt.Println("Every hour on the half hour") })
c.AddFunc("@hourly", func() { fmt.Println("Every hour") })
c.AddFunc("@every 1h30m", func() { fmt.Println("Every hour thirty") })
c.Start()
..
// Funcs are invoked in their own goroutine, asynchronously.
...
// Funcs may also be added to a running Cron
c.AddFunc("@daily", func() { fmt.Println("Every day") })
..
// Inspect the cron job entries' next and previous run times.
inspect(c.Entries())
..
c.Stop() // Stop the scheduler (does not stop any jobs already running).
CRON Expression Format ¶
A cron expression represents a set of times, using 6 space-separated fields.
Field name | Mandatory? | Allowed values | Allowed special characters ---------- | ---------- | -------------- | -------------------------- Seconds | Yes | 0-59 | * / , - Minutes | Yes | 0-59 | * / , - Hours | Yes | 0-23 | * / , - Day of month | Yes | 1-31 | * / , - ? Month | Yes | 1-12 or JAN-DEC | * / , - Day of week | Yes | 0-6 or SUN-SAT | * / , - ?
Note: Month and Day-of-week field values are case insensitive. "SUN", "Sun", and "sun" are equally accepted.
Special Characters ¶
Asterisk ( * )
The asterisk indicates that the cron expression will match for all values of the field; e.g., using an asterisk in the 5th field (month) would indicate every month.
Slash ( / )
Slashes are used to describe increments of ranges. For example 3-59/15 in the 1st field (minutes) would indicate the 3rd minute of the hour and every 15 minutes thereafter. The form "*\/..." is equivalent to the form "first-last/...", that is, an increment over the largest possible range of the field. The form "N/..." is accepted as meaning "N-MAX/...", that is, starting at N, use the increment until the end of that specific range. It does not wrap around.
Comma ( , )
Commas are used to separate items of a list. For example, using "MON,WED,FRI" in the 5th field (day of week) would mean Mondays, Wednesdays and Fridays.
Hyphen ( - )
Hyphens are used to define ranges. For example, 9-17 would indicate every hour between 9am and 5pm inclusive.
Question mark ( ? )
Question mark may be used instead of '*' for leaving either day-of-month or day-of-week blank.
Predefined schedules ¶
You may use one of several pre-defined schedules in place of a cron expression.
Entry | Description | Equivalent To ----- | ----------- | ------------- @yearly (or @annually) | Run once a year, midnight, Jan. 1st | 0 0 0 1 1 * @monthly | Run once a month, midnight, first of month | 0 0 0 1 * * @weekly | Run once a week, midnight between Sat/Sun | 0 0 0 * * 0 @daily (or @midnight) | Run once a day, midnight | 0 0 0 * * * @hourly | Run once an hour, beginning of hour | 0 0 * * * *
Intervals ¶
You may also schedule a job to execute at fixed intervals, starting at the time it's added or cron is run. This is supported by formatting the cron spec like this:
@every <duration>
where "duration" is a string accepted by time.ParseDuration (http://golang.org/pkg/time/#ParseDuration).
For example, "@every 1h30m10s" would indicate a schedule that activates after 1 hour, 30 minutes, 10 seconds, and then every interval after that.
Note: The interval does not take the job runtime into account. For example, if a job takes 3 minutes to run, and it is scheduled to run every 5 minutes, it will have only 2 minutes of idle time between each run.
Time zones ¶
All interpretation and scheduling is done in the machine's local time zone (as provided by the Go time package (http://www.golang.org/pkg/time).
Be aware that jobs scheduled during daylight-savings leap-ahead transitions will not be run!
Thread safety ¶
Since the Cron service runs concurrently with the calling code, some amount of care must be taken to ensure proper synchronization.
All cron methods are designed to be correctly synchronized as long as the caller ensures that invocations have a clear happens-before ordering between them.
Implementation ¶
Cron entries are stored in an array, sorted by their next activation time. Cron sleeps until the next job is due to be run.
Upon waking:
- it runs each entry that is active on that second
- it calculates the next run times for the jobs that were run
- it re-sorts the array of entries by next activation time.
- it goes to sleep until the soonest job.
Index ¶
- Variables
- func Disabled(_ *Cron, entry *Entry)
- func Label(label string) func(*Cron, *Entry)
- func RunOnStart(c *Cron, entry *Entry)
- func WithID(id EntryID) func(*Cron, *Entry)
- func WithNext(next time.Time) func(*Cron, *Entry)
- type Config
- type ConstantDelaySchedule
- type Cron
- func (c *Cron) AddEntry(entry Entry, opts ...EntryOption) (EntryID, error)
- func (c *Cron) AddJob(spec string, job IntoJob, opts ...EntryOption) (EntryID, error)
- func (c *Cron) AddJob1(spec string, job Job, opts ...EntryOption) (EntryID, error)
- func (c *Cron) CancelRun(entryID EntryID, runID RunID) error
- func (c *Cron) CompletedJobRunsFor(entryID EntryID) ([]JobRun, error)
- func (c *Cron) Disable(id EntryID)
- func (c *Cron) Enable(id EntryID)
- func (c *Cron) Entries() []Entry
- func (c *Cron) Entry(id EntryID) (Entry, error)
- func (c *Cron) GetCleanupTS() time.Time
- func (c *Cron) GetNextTime() time.Time
- func (c *Cron) GetRun(entryID EntryID, runID RunID) (JobRun, error)
- func (c *Cron) IsRunning(id EntryID) bool
- func (c *Cron) JobRunCompletedCh() <-chan *jobRunStruct
- func (c *Cron) JobRunCreatedCh() <-chan *jobRunStruct
- func (c *Cron) Location() *time.Location
- func (c *Cron) Remove(id EntryID)
- func (c *Cron) Run() (started bool)
- func (c *Cron) RunNow(id EntryID) error
- func (c *Cron) RunningJobs() []JobRun
- func (c *Cron) RunningJobsFor(entryID EntryID) ([]JobRun, error)
- func (c *Cron) Schedule(schedule Schedule, job Job, opts ...EntryOption) (EntryID, error)
- func (c *Cron) SetLocation(newLoc *time.Location)
- func (c *Cron) Start() (started bool)
- func (c *Cron) Stop() <-chan struct{}
- func (c *Cron) Sub(id EntryID) *pubsub.Sub[EntryID, JobEvent]
- func (c *Cron) UpdateLabel(id EntryID, label string)
- func (c *Cron) UpdateSchedule(id EntryID, schedule Schedule) error
- func (c *Cron) UpdateScheduleWithSpec(id EntryID, spec string) error
- type Entry
- type EntryHeap
- type EntryID
- type EntryIDFactory
- type EntryOption
- type FuncEntryIDFactory
- type FuncJob
- type IntoJob
- type Job
- func Chain(j IntoJob, wrappers ...JobWrapper) Job
- func J(v IntoJob) Job
- func N(n int, j IntoJob) Job
- func Once(job IntoJob) Job
- func SkipIfStillRunning(j IntoJob) Job
- func WithDeadline(deadline time.Time, job IntoJob) Job
- func WithJitter(duration time.Duration, job IntoJob) Job
- func WithTimeout(d time.Duration, job IntoJob) Job
- type Job1
- type Job1Wrapper
- type Job2
- type Job2Wrapper
- type Job3
- type Job3Wrapper
- type Job4
- type Job4Wrapper
- type Job5
- type Job5Wrapper
- type Job6
- type Job6Wrapper
- type Job7
- type Job7Wrapper
- type Job8
- type Job8Wrapper
- type Job9
- type Job9Wrapper
- type Job10
- type Job10Wrapper
- type Job11
- type Job11Wrapper
- type Job12
- type Job12Wrapper
- type Job13
- type Job13Wrapper
- type Job14
- type Job14Wrapper
- type Job15
- type Job15Wrapper
- type Job16
- type Job16Wrapper
- type Job17
- type Job17Wrapper
- type Job18
- type Job18Wrapper
- type Job19
- type Job19Wrapper
- type Job20
- type Job20Wrapper
- type Job21
- type Job21Wrapper
- type Job22
- type Job22Wrapper
- type Job23
- type Job23Wrapper
- type JobEvent
- type JobEventType
- type JobRun
- type JobWrapper
- type Option
- type ParseOption
- type Parser
- type RunID
- type Schedule
- type ScheduleParser
- type SpecSchedule
Constants ¶
This section is empty.
Variables ¶
var ErrEntryNotFound = errors.New("entry not found")
ErrEntryNotFound ...
var ErrIDAlreadyUsed = errors.New("id already used")
ErrIDAlreadyUsed ...
var ErrJobAlreadyRunning = errors.New("job already running")
ErrJobAlreadyRunning ...
var ErrRunNotFound = errors.New("run not found")
ErrRunNotFound ...
var ErrUnsupportedJobType = errors.New("unsupported job type")
ErrUnsupportedJobType ...
var SecondParser = NewParser(Second | Minute | Hour | Dom | Month | DowOptional | Descriptor)
Functions ¶
func RunOnStart ¶
Types ¶
type Config ¶
type Config struct {
Ctx context.Context
Location *time.Location
Clock clockwork.Clock
Logger *log.Logger
Parser ScheduleParser
IDFactory EntryIDFactory
KeepCompletedRunsDur *time.Duration
}
Config ...
type ConstantDelaySchedule ¶
ConstantDelaySchedule represents a simple recurring duty cycle, e.g. "Every 5 minutes". It does not support jobs more frequent than once a second.
func Every ¶
func Every(duration time.Duration) ConstantDelaySchedule
Every returns a crontab Schedule that activates once every duration. Delays of less than a second are not supported (will round up to 1 second). Any fields less than a Second are truncated.
type Cron ¶
type Cron struct {
// contains filtered or unexported fields
}
Cron keeps track of any number of entries, invoking the associated func as specified by the schedule. It may be started, stopped, and the entries may be inspected while running.
func (*Cron) AddEntry ¶
func (c *Cron) AddEntry(entry Entry, opts ...EntryOption) (EntryID, error)
AddEntry ...
func (*Cron) CompletedJobRunsFor ¶
CompletedJobRunsFor ...
func (*Cron) GetNextTime ¶
GetNextTime returns the next time a job is scheduled to be executed If no job is scheduled to be executed, the Zero time is returned
func (*Cron) JobRunCompletedCh ¶
func (c *Cron) JobRunCompletedCh() <-chan *jobRunStruct
JobRunCompletedCh ...
func (*Cron) JobRunCreatedCh ¶
func (c *Cron) JobRunCreatedCh() <-chan *jobRunStruct
JobRunCreatedCh ...
func (*Cron) RunningJobsFor ¶
RunningJobsFor ...
func (*Cron) SetLocation ¶
SetLocation sets a new location to use. Re-set the "Next" values for all entries. Re-sort entries and run due entries.
func (*Cron) Stop ¶
func (c *Cron) Stop() <-chan struct{}
Stop stops the cron scheduler if it is running; otherwise it does nothing. A context is returned so the caller can wait for running jobs to complete.
func (*Cron) UpdateSchedule ¶
UpdateSchedule ...
type Entry ¶
type Entry struct {
ID EntryID
Spec *string
// The schedule on which this job should be run.
Schedule Schedule
// The next time the job will run. This is the zero time if Cron has not been started or this entry's schedule is unsatisfiable
Next time.Time
// The last time this job was run. This is the zero time if the job has never been run.
Prev time.Time
// Label to describe the job
Label string
// Either or not the job is currently active
Active bool
// contains filtered or unexported fields
}
Entry consists of a schedule and the func to execute on that schedule.
type EntryIDFactory ¶
type EntryIDFactory interface {
Next() EntryID
}
func UUIDEntryIDFactory ¶
func UUIDEntryIDFactory() EntryIDFactory
UUIDEntryIDFactory generate and format UUID V4
type EntryOption ¶
type FuncEntryIDFactory ¶
type FuncEntryIDFactory func() EntryID
func (FuncEntryIDFactory) Next ¶
func (f FuncEntryIDFactory) Next() EntryID
type Job ¶
Job is an interface for submitted cron jobs.
func Chain ¶
func Chain(j IntoJob, wrappers ...JobWrapper) Job
Chain `Chain(j, w1, w2, w3)` -> `w3(w2(w1(j)))`
func J ¶
J is a helper to turn a IntoJob into a Job Any of these functions, or anything that have a "Run" method with one of these signatures can be casted into a Job. func() func() error func(context.Context) func(context.Context) error func(cron.EntryID) func(cron.EntryID) error func(cron.Entry) func(cron.Entry) error func(*cron.Cron) func(*cron.Cron) error func(context.Context, cron.EntryID) func(context.Context, cron.EntryID) error func(context.Context, cron.Entry) func(context.Context, cron.Entry) error func(context.Context, *cron.Cron) func(context.Context, *cron.Cron) error func(*cron.Cron, cron.EntryID) func(*cron.Cron, cron.EntryID) error func(*cron.Cron, cron.Entry) func(*cron.Cron, cron.Entry) error func(context.Context, *cron.Cron, cron.EntryID) func(context.Context, *cron.Cron, cron.EntryID) error func(context.Context, *cron.Cron, cron.Entry) func(context.Context, *cron.Cron, cron.Entry) error
func SkipIfStillRunning ¶
SkipIfStillRunning skips an invocation of the Job if a previous invocation is still running.
func WithJitter ¶
WithJitter add some random delay before running the job
type Job1Wrapper ¶
type Job1Wrapper struct{ Job1 }
type Job2Wrapper ¶
type Job2Wrapper struct{ Job2 }
type Job3Wrapper ¶
type Job3Wrapper struct{ Job3 }
type Job4Wrapper ¶
type Job4Wrapper struct{ Job4 }
type Job5Wrapper ¶
type Job5Wrapper struct{ Job5 }
type Job6Wrapper ¶
type Job6Wrapper struct{ Job6 }
type Job7Wrapper ¶
type Job7Wrapper struct{ Job7 }
type Job8Wrapper ¶
type Job8Wrapper struct{ Job8 }
type Job9Wrapper ¶
type Job9Wrapper struct{ Job9 }
type Job10Wrapper ¶
type Job10Wrapper struct{ Job10 }
type Job11Wrapper ¶
type Job11Wrapper struct{ Job11 }
type Job12Wrapper ¶
type Job12Wrapper struct{ Job12 }
type Job13Wrapper ¶
type Job13Wrapper struct{ Job13 }
type Job14Wrapper ¶
type Job14Wrapper struct{ Job14 }
type Job15Wrapper ¶
type Job15Wrapper struct{ Job15 }
type Job16Wrapper ¶
type Job16Wrapper struct{ Job16 }
type Job17Wrapper ¶
type Job17Wrapper struct{ Job17 }
type Job18Wrapper ¶
type Job18Wrapper struct{ Job18 }
type Job19Wrapper ¶
type Job19Wrapper struct{ Job19 }
type Job20Wrapper ¶
type Job20Wrapper struct{ Job20 }
type Job21Wrapper ¶
type Job21Wrapper struct{ Job21 }
type Job22Wrapper ¶
type Job22Wrapper struct{ Job22 }
type Job23Wrapper ¶
type Job23Wrapper struct{ Job23 }
type JobEvent ¶
type JobEvent struct {
Typ JobEventType
JobRun JobRun
CreatedAt time.Time
}
func NewJobEvent ¶
func NewJobEvent(typ JobEventType, jobRun *jobRunStruct) JobEvent
type JobEventType ¶
type JobEventType int
const ( Start JobEventType = iota + 1 Completed CompletedNoErr CompletedErr CompletedPanic )
func (JobEventType) String ¶
func (e JobEventType) String() string
type JobWrapper ¶
func DeadlineWrapper ¶
func DeadlineWrapper(deadline time.Time) JobWrapper
func JitterWrapper ¶
func JitterWrapper(duration time.Duration) JobWrapper
JitterWrapper add some random delay before running the job
func NWrapper ¶
func NWrapper(n int) JobWrapper
func TimeoutWrapper ¶
func TimeoutWrapper(duration time.Duration) JobWrapper
TimeoutWrapper automatically cancel the job context after a given duration
type Option ¶
type Option func(*Config)
Option represents a modification to the default behavior of a Cron.
func WithLocation ¶
WithLocation overrides the timezone of the cron instance.
func WithParser ¶
func WithParser(p ScheduleParser) Option
WithParser overrides the parser used for interpreting job schedules.
type ParseOption ¶
type ParseOption int
Configuration options for creating a parser. Most options specify which fields should be included, while others enable features. If a field is not included the parser will assume a default value. These options do not change the order fields are parse in.
const ( Second ParseOption = 1 << iota // Seconds field, default 0 SecondOptional // Optional seconds field, default 0 Minute // Minutes field, default 0 Hour // Hours field, default 0 Dom // Day of month field, default * Month // Month field, default * Dow // Day of week field, default * DowOptional // Optional day of week field, default * Descriptor // Allow descriptors such as @monthly, @weekly, etc. )
type Parser ¶
type Parser struct {
// contains filtered or unexported fields
}
A custom Parser that can be configured.
func NewParser ¶
func NewParser(options ParseOption) Parser
NewParser creates a Parser with custom options.
It panics if more than one Optional is given, since it would be impossible to correctly infer which optional is provided or missing in general.
Examples
// Standard parser without descriptors
specParser := NewParser(Minute | Hour | Dom | Month | Dow)
sched, err := specParser.Parse("0 0 15 */3 *")
// Same as above, just excludes time fields
specParser := NewParser(Dom | Month | Dow)
sched, err := specParser.Parse("15 */3 *")
// Same as above, just makes Dow optional
specParser := NewParser(Dom | Month | DowOptional)
sched, err := specParser.Parse("15 */3")
type Schedule ¶
type Schedule interface {
// Next return the next activation time, later than the given time.
// Next is invoked initially, and then each time the job is run.
Next(time.Time) time.Time
}
The Schedule describes a job's duty cycle.
func ParseStandard ¶
ParseStandard returns a new crontab schedule representing the given standardSpec (https://en.wikipedia.org/wiki/Cron). It requires 5 entries representing: minute, hour, day of month, month and day of week, in that order. It returns a descriptive error if the spec is not valid.
It accepts
- Standard crontab specs, e.g. "* * * * ?"
- Descriptors, e.g. "@midnight", "@every 1h30m"
type ScheduleParser ¶
ScheduleParser is an interface for schedule spec parsers that return a Schedule
type SpecSchedule ¶
type SpecSchedule struct {
Second, Minute, Hour, Dom, Month, Dow uint64
// Override location for this schedule.
Location *time.Location
}
SpecSchedule specifies a duty cycle (to the second granularity), based on a traditional crontab specification. It is computed initially and stored as bit sets.