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