diff options
Diffstat (limited to 'vendor/codeberg.org/gruf/go-sched/job.go')
-rw-r--r-- | vendor/codeberg.org/gruf/go-sched/job.go | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/vendor/codeberg.org/gruf/go-sched/job.go b/vendor/codeberg.org/gruf/go-sched/job.go new file mode 100644 index 000000000..66e24fe9a --- /dev/null +++ b/vendor/codeberg.org/gruf/go-sched/job.go @@ -0,0 +1,99 @@ +package sched + +import ( + "time" + + "codeberg.org/gruf/go-atomics" +) + +// Job encapsulates logic for a scheduled job to be run according +// to a set Timing, executing the job with a set panic handler, and +// holding onto a next execution time safely in a concurrent environment. +type Job struct { + id uint64 + next atomics.Time + timing Timing + call func(time.Time) + panic func(interface{}) +} + +// NewJob returns a new Job to run given function. +func NewJob(fn func(now time.Time)) *Job { + if fn == nil { + // Ensure a function + panic("nil func") + } + + j := &Job{ // set defaults + timing: emptytiming, // i.e. fire immediately + call: fn, + panic: func(i interface{}) { panic(i) }, + } + + // Init next time ptr + j.next.Store(zerotime) + + return j +} + +// At sets this Job to execute at time, by passing (*sched.Once)(&at) to .With(). See .With() for details. +func (job *Job) At(at time.Time) *Job { + return job.With((*Once)(&at)) +} + +// Every sets this Job to execute every period, by passing sched.Period(period) to .With(). See .With() for details. +func (job *Job) Every(period time.Duration) *Job { + return job.With(Periodic(period)) +} + +// EveryAt sets this Job to execute every period starting at time, by passing &PeriodicAt{once: Once(at), period: Periodic(period)} to .With(). See .With() for details. +func (job *Job) EveryAt(at time.Time, period time.Duration) *Job { + return job.With(&PeriodicAt{Once: Once(at), Period: Periodic(period)}) +} + +// With sets this Job's timing to given implementation, or if already set will wrap existing using sched.TimingWrap{}. +func (job *Job) With(t Timing) *Job { + if t == nil { + // Ensure a timing + panic("nil Timing") + } + + if job.timing == emptytiming { + // Set new timing + job.timing = t + } else { + // Wrap old timing + old := job.timing + job.timing = &TimingWrap{ + Outer: t, + Inner: old, + } + } + + return job +} + +// Panic specifics how this job handles panics, default is an actual panic. +func (job *Job) Panic(fn func(interface{})) *Job { + if fn == nil { + // Ensure a function + panic("nil func") + } + job.panic = fn + return job +} + +// Next returns the next time this Job is expected to run. +func (job *Job) Next() time.Time { + return job.next.Load() +} + +// Run will execute this Job and pass through given now time. +func (job *Job) Run(now time.Time) { + defer func() { + if r := recover(); r != nil { + job.panic(r) + } + }() + job.call(now) +} |