diff options
Diffstat (limited to 'vendor/codeberg.org/gruf/go-sched/timing.go')
-rw-r--r-- | vendor/codeberg.org/gruf/go-sched/timing.go | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/vendor/codeberg.org/gruf/go-sched/timing.go b/vendor/codeberg.org/gruf/go-sched/timing.go new file mode 100644 index 000000000..33c230fa5 --- /dev/null +++ b/vendor/codeberg.org/gruf/go-sched/timing.go @@ -0,0 +1,92 @@ +package sched + +import ( + "time" +) + +var ( + // zerotime is zero time.Time (unix epoch). + zerotime = time.Time{} + + // emptytiming is a global timingempty to check against. + emptytiming = timingempty{} +) + +// Timing provides scheduling for a Job, determining the next time +// for given current time that execution is required. Please note that +// calls to .Next() may alter the results of the next call, and should +// only be called by the Scheduler. +type Timing interface { + Next(time.Time) time.Time +} + +// timingempty is a 'zero' Timing implementation that always returns zero time. +type timingempty struct{} + +func (timingempty) Next(time.Time) time.Time { + return zerotime +} + +// Once implements Timing to provide a run-once Job execution. +type Once time.Time + +func (o *Once) Next(time.Time) time.Time { + ret := *(*time.Time)(o) + *o = Once(zerotime) // reset + return ret +} + +// Periodic implements Timing to provide a recurring Job execution. +type Periodic time.Duration + +func (p Periodic) Next(now time.Time) time.Time { + return now.Add(time.Duration(p)) +} + +// PeriodicAt implements Timing to provide a recurring Job execution starting at 'Once' time. +type PeriodicAt struct { + Once Once + Period Periodic +} + +func (p *PeriodicAt) Next(now time.Time) time.Time { + if next := p.Once.Next(now); !next.IsZero() { + return next + } + return p.Period.Next(now) +} + +// TimingWrap allows combining two different Timing implementations. +type TimingWrap struct { + Outer Timing + Inner Timing + + // determined next times + outerNext time.Time + innerNext time.Time +} + +func (t *TimingWrap) Next(now time.Time) time.Time { + if t.outerNext.IsZero() { + // Regenerate outermost next run time + t.outerNext = t.Outer.Next(now) + } + + if t.innerNext.IsZero() { + // Regenerate innermost next run time + t.innerNext = t.Inner.Next(now) + } + + // If outer comes before inner, return outer + if t.outerNext != zerotime && + t.outerNext.Before(t.innerNext) { + next := t.outerNext + t.outerNext = zerotime + return next + } + + // Else, return inner + next := t.innerNext + t.innerNext = zerotime + return next +} |