2024-09-24 16:10:43 +02:00

77 lines
1.1 KiB
Go

package scheduler
import (
"context"
"cycle-scheduler/internal/job"
"sync"
"sync/atomic"
"time"
)
// safeTime wraps a `time.Timer` with a lock to be thread safe.
type safeTimer struct {
l sync.Mutex
timer *time.Timer
}
func (st *safeTimer) stop() {
if st.timer != nil {
st.timer.Stop()
}
}
// set replaces the current timer.
// It also ensures that the current timer is stopped.
func (st *safeTimer) set(t *time.Timer) {
st.l.Lock()
defer st.l.Unlock()
if st.timer != nil {
st.timer.Stop()
st.timer = t
return
}
st.timer = t
}
type TaskDetails struct {
job.JobDetails
Attempts int `json:"attempts"`
}
type task struct {
*job.Job
attempts atomic.Uint32
timer *safeTimer
}
func newTask(f job.FnJob) *task {
j := job.NewJob(f)
t := task{
Job: &j,
timer: &safeTimer{},
}
return &t
}
func (t *task) abort() {
if t.timer != nil {
t.timer.stop()
}
t.Job.Abort()
}
func (t *task) run(ctx context.Context) {
t.attempts.Add(1)
t.Job.Run(ctx)
}
func (t *task) getDetails() TaskDetails {
return TaskDetails{
JobDetails: t.IntoDetails(),
Attempts: int(t.attempts.Load()),
}
}