mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2024-12-21 02:03:19 +00:00
93 lines
2 KiB
Go
93 lines
2 KiB
Go
|
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
|
||
|
}
|