summaryrefslogtreecommitdiff
path: root/vendor/codeberg.org/gruf/go-sched/timing.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/codeberg.org/gruf/go-sched/timing.go')
-rw-r--r--vendor/codeberg.org/gruf/go-sched/timing.go92
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
+}