mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2024-11-14 13:31:03 +00:00
d20ec967c4
* update go-cache library to fix critical bug regarding cache sweep scheduling Signed-off-by: kim <grufwub@gmail.com> * update go-sched Signed-off-by: kim <grufwub@gmail.com>
118 lines
2.9 KiB
Go
118 lines
2.9 KiB
Go
package sched
|
|
|
|
import (
|
|
"reflect"
|
|
"strconv"
|
|
"strings"
|
|
"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)
|
|
}
|
|
|
|
// String provides a debuggable string representation of Job including ID, next time and Timing type.
|
|
func (job *Job) String() string {
|
|
var buf strings.Builder
|
|
buf.WriteByte('{')
|
|
buf.WriteString("id=")
|
|
buf.WriteString(strconv.FormatUint(job.id, 10))
|
|
buf.WriteByte(' ')
|
|
buf.WriteString("next=")
|
|
buf.WriteString(job.next.Load().Format(time.StampMicro))
|
|
buf.WriteByte(' ')
|
|
buf.WriteString("timing=")
|
|
buf.WriteString(reflect.TypeOf(job.timing).String())
|
|
buf.WriteByte('}')
|
|
return buf.String()
|
|
}
|