72 lines
1.0 KiB
Go
72 lines
1.0 KiB
Go
package scheduler
|
|
|
|
import (
|
|
"context"
|
|
"cycle-scheduler/internal/job"
|
|
"sync/atomic"
|
|
"time"
|
|
)
|
|
|
|
// atomicTimer wraps a `time.Timer`.
|
|
type atomicTimer struct {
|
|
atomic.Pointer[time.Timer]
|
|
}
|
|
|
|
func (at *atomicTimer) stop() {
|
|
timer := at.Load()
|
|
if timer != nil {
|
|
timer.Stop()
|
|
}
|
|
}
|
|
|
|
// set replaces the current timer.
|
|
// It also ensures that the current timer is stopped.
|
|
func (at *atomicTimer) set(t *time.Timer) {
|
|
timer := at.Load()
|
|
if timer != nil {
|
|
timer.Stop()
|
|
at.Swap(t)
|
|
return
|
|
}
|
|
|
|
at.Swap(t)
|
|
}
|
|
|
|
type TaskDetails struct {
|
|
job.JobDetails
|
|
Attempts int `json:"attempts"`
|
|
}
|
|
|
|
type task struct {
|
|
*job.Job
|
|
attempts atomic.Uint32
|
|
timer atomicTimer
|
|
}
|
|
|
|
func newTask(f job.FnJob) *task {
|
|
j := job.NewJob(f)
|
|
t := task{
|
|
Job: &j,
|
|
timer: atomicTimer{},
|
|
}
|
|
|
|
return &t
|
|
}
|
|
|
|
func (t *task) abort() {
|
|
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()),
|
|
}
|
|
}
|