T2.2: Migrate scheduler to use domain.Schedule
Parse each job's schedule once on load (resetNextRuns) and on edit (RefreshSchedule) via the new parseJobSchedule helper, caching the result in a map[int]domain.Schedule keyed by job ID. prepareNextRun now looks up the cached Schedule instead of re-parsing the string on every call. Remove the nextRunTime wrapper that did the per-call parsing. Drop the three scheduler_test.go tests that duplicated coverage already in domain/schedule_test.go. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+27
-22
@@ -21,20 +21,22 @@ type Scheduler struct {
|
||||
jobs *[]domain.Job
|
||||
onChange func(domain.RunRecord)
|
||||
|
||||
mu sync.Mutex
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
paused bool
|
||||
mu sync.Mutex
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
paused bool
|
||||
schedules map[int]domain.Schedule // parsed once per job on load/edit
|
||||
}
|
||||
|
||||
func NewScheduler(store *storage.Store, jobs *[]domain.Job, onChange func(domain.RunRecord)) *Scheduler {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
s := &Scheduler{
|
||||
store: store,
|
||||
jobs: jobs,
|
||||
onChange: onChange,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
store: store,
|
||||
jobs: jobs,
|
||||
onChange: onChange,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
schedules: make(map[int]domain.Schedule),
|
||||
}
|
||||
s.resetNextRuns(time.Now())
|
||||
return s
|
||||
@@ -107,6 +109,7 @@ func (s *Scheduler) RefreshSchedule(index int) {
|
||||
return
|
||||
}
|
||||
job := &(*s.jobs)[index]
|
||||
s.parseJobSchedule(job) // re-parse in case the schedule string changed
|
||||
if !job.Enabled {
|
||||
job.NextRun = "Paused"
|
||||
return
|
||||
@@ -207,6 +210,7 @@ func runningOutput(job domain.Job, trigger string, started time.Time) string {
|
||||
func (s *Scheduler) resetNextRuns(now time.Time) {
|
||||
for index := range *s.jobs {
|
||||
job := &(*s.jobs)[index]
|
||||
s.parseJobSchedule(job) // parse once on load
|
||||
if !job.Enabled {
|
||||
job.NextRun = "Paused"
|
||||
continue
|
||||
@@ -216,24 +220,25 @@ func (s *Scheduler) resetNextRuns(now time.Time) {
|
||||
_ = s.store.SaveJobs(*s.jobs)
|
||||
}
|
||||
|
||||
// parseJobSchedule caches a parsed domain.Schedule for the job. Invalid
|
||||
// schedule strings are silently dropped from the cache so prepareNextRun can
|
||||
// distinguish them from valid ones.
|
||||
func (s *Scheduler) parseJobSchedule(job *domain.Job) {
|
||||
sched, err := domain.Parse(job.Schedule)
|
||||
if err != nil {
|
||||
delete(s.schedules, job.ID)
|
||||
return
|
||||
}
|
||||
s.schedules[job.ID] = sched
|
||||
}
|
||||
|
||||
func (s *Scheduler) prepareNextRun(job *domain.Job, from time.Time) {
|
||||
next, ok := nextRunTime(job.Schedule, from)
|
||||
sched, ok := s.schedules[job.ID]
|
||||
if !ok {
|
||||
job.NextRun = "Invalid schedule"
|
||||
job.NextDue = time.Time{}
|
||||
return
|
||||
}
|
||||
job.NextDue = next
|
||||
job.NextDue = sched.Next(from)
|
||||
job.NextRun = job.NextDue.Format("2006-01-02 15:04:05")
|
||||
}
|
||||
|
||||
// nextRunTime is a thin wrapper over domain.Schedule kept for the scheduler's
|
||||
// existing call sites. It parses the schedule on every call for now; T2.2
|
||||
// replaces this with a Schedule parsed once on load/edit.
|
||||
func nextRunTime(schedule string, from time.Time) (time.Time, bool) {
|
||||
parsed, err := domain.Parse(schedule)
|
||||
if err != nil {
|
||||
return time.Time{}, false
|
||||
}
|
||||
return parsed.Next(from), true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user