Skip to content

Commit c753d99

Browse files
authored
Merge branch 'v2' into feature/scheduler-monitor
2 parents 1b9273e + 9cc3be7 commit c753d99

File tree

6 files changed

+88
-8
lines changed

6 files changed

+88
-8
lines changed

.github/workflows/codeql-analysis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jobs:
3939

4040
steps:
4141
- name: Checkout repository
42-
uses: actions/checkout@v5
42+
uses: actions/checkout@v6
4343

4444
# Initializes the CodeQL tools for scanning.
4545
- name: Initialize CodeQL

.github/workflows/file_formatting.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
runs-on: ubuntu-latest
1414
steps:
1515
- name: checkout code
16-
uses: actions/checkout@v5
16+
uses: actions/checkout@v6
1717
- name: verify example_test.go
1818
run: |
1919
grep "^func [a-z-A-Z]" example_test.go | sort -c

.github/workflows/go_test.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ jobs:
1818
runs-on: ubuntu-latest
1919
steps:
2020
- name: Checkout code
21-
uses: actions/checkout@v5
21+
uses: actions/checkout@v6
2222
- name: Install Go
2323
uses: actions/setup-go@v6
2424
with:
2525
go-version: ${{ matrix.go-version }}
2626
- name: golangci-lint
27-
uses: golangci/golangci-lint-action@v9.0.0
27+
uses: golangci/golangci-lint-action@v9.1.0
2828
with:
2929
version: v2.4.0
3030
- name: test

job.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,16 +1022,14 @@ type weeklyJob struct {
10221022
}
10231023

10241024
func (w weeklyJob) next(lastRun time.Time) time.Time {
1025-
firstPass := true
1026-
next := w.nextWeekDayAtTime(lastRun, firstPass)
1025+
next := w.nextWeekDayAtTime(lastRun, true)
10271026
if !next.IsZero() {
10281027
return next
10291028
}
1030-
firstPass = false
10311029

10321030
startOfTheNextIntervalWeek := (lastRun.Day() - int(lastRun.Weekday())) + int(w.interval*7)
10331031
from := time.Date(lastRun.Year(), lastRun.Month(), startOfTheNextIntervalWeek, 0, 0, 0, 0, lastRun.Location())
1034-
return w.nextWeekDayAtTime(from, firstPass)
1032+
return w.nextWeekDayAtTime(from, false)
10351033
}
10361034

10371035
func (w weeklyJob) nextWeekDayAtTime(lastRun time.Time, firstPass bool) time.Time {

scheduler.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,12 @@ func (s *scheduler) selectNewJob(in newJobIn) {
519519
next = j.next(s.now())
520520
}
521521

522+
if next.Before(s.now()) {
523+
for next.Before(s.now()) {
524+
next = j.next(next)
525+
}
526+
}
527+
522528
id := j.id
523529
j.timer = s.exec.clock.AfterFunc(next.Sub(s.now()), func() {
524530
select {
@@ -574,6 +580,11 @@ func (s *scheduler) selectStart() {
574580
if next.IsZero() {
575581
next = j.next(s.now())
576582
}
583+
if next.Before(s.now()) {
584+
for next.Before(s.now()) {
585+
next = j.next(next)
586+
}
587+
}
577588

578589
jobID := id
579590
j.timer = s.exec.clock.AfterFunc(next.Sub(s.now()), func() {
@@ -831,6 +842,11 @@ func (s *scheduler) RemoveJob(id uuid.UUID) error {
831842
}
832843

833844
func (s *scheduler) Start() {
845+
if s.started.Load() {
846+
s.logger.Warn("gocron: scheduler already started")
847+
return
848+
}
849+
834850
select {
835851
case <-s.shutdownCtx.Done():
836852
// Scheduler already shut down, don't notify

scheduler_test.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,41 @@ func TestScheduler_Shutdown(t *testing.T) {
578578
})
579579
}
580580

581+
func TestScheduler_Start(t *testing.T) {
582+
defer verifyNoGoroutineLeaks(t)
583+
584+
t.Run("calling start multiple times is a no-op", func(t *testing.T) {
585+
s := newTestScheduler(t)
586+
587+
var counter int
588+
var mu sync.Mutex
589+
590+
_, err := s.NewJob(
591+
DurationJob(
592+
100*time.Millisecond,
593+
),
594+
NewTask(
595+
func() {
596+
mu.Lock()
597+
counter++
598+
mu.Unlock()
599+
},
600+
),
601+
)
602+
require.NoError(t, err)
603+
604+
s.Start()
605+
s.Start()
606+
s.Start()
607+
608+
time.Sleep(1000 * time.Millisecond)
609+
610+
require.NoError(t, s.Shutdown())
611+
612+
assert.Contains(t, []int{9, 10}, counter)
613+
})
614+
}
615+
581616
func TestScheduler_NewJob(t *testing.T) {
582617
defer verifyNoGoroutineLeaks(t)
583618
tests := []struct {
@@ -2876,3 +2911,34 @@ func TestScheduler_WithMonitor(t *testing.T) {
28762911
})
28772912
}
28782913
}
2914+
2915+
func TestScheduler_WithStartAtDateTimePast(t *testing.T) {
2916+
defer verifyNoGoroutineLeaks(t)
2917+
2918+
// Monday
2919+
testTime := time.Date(2024, time.January, 1, 9, 0, 0, 0, time.UTC)
2920+
2921+
fakeClock := clockwork.NewFakeClockAt(testTime)
2922+
2923+
s := newTestScheduler(t, WithClock(fakeClock))
2924+
j, err := s.NewJob(
2925+
WeeklyJob(2, NewWeekdays(time.Sunday), NewAtTimes(NewAtTime(10, 0, 0))),
2926+
NewTask(func() {}),
2927+
WithStartAt(
2928+
// The start time is in the past (Dec 30, 2023 9am) which is a Saturday
2929+
WithStartDateTimePast(testTime.Add(-time.Hour*24*2)),
2930+
),
2931+
)
2932+
require.NoError(t, err)
2933+
2934+
s.Start()
2935+
2936+
nextRun, err := j.NextRun()
2937+
require.NoError(t, err)
2938+
2939+
require.NoError(t, s.Shutdown())
2940+
2941+
// Because the start time was in the past - we expect it to schedule 2 intervals ahead, pasing the first available Sunday
2942+
// which was in the past Dec 31, 2023, so the next is Jan 7, 2024
2943+
assert.Equal(t, time.Date(2024, time.January, 7, 10, 0, 0, 0, time.UTC), nextRun)
2944+
}

0 commit comments

Comments
 (0)