From b04e3b9a0920077d911f339a4ee2a8750ce50720 Mon Sep 17 00:00:00 2001 From: John Roesler Date: Wed, 8 Oct 2025 16:10:01 -0500 Subject: [PATCH] fix: multiple calls to shutdown should be no-op --- scheduler.go | 9 +++++++++ scheduler_test.go | 10 ++++++++++ 2 files changed, 19 insertions(+) diff --git a/scheduler.go b/scheduler.go index c532e28..f0c0e20 100644 --- a/scheduler.go +++ b/scheduler.go @@ -233,6 +233,12 @@ func NewScheduler(options ...SchedulerOption) (Scheduler, error) { func (s *scheduler) stopScheduler() { s.logger.Debug("gocron: stopping scheduler") + if !s.started { + s.logger.Debug("gocron: scheduler already stopped") + s.stopErrCh <- nil + return + } + if s.started { s.exec.stopCh <- struct{}{} } @@ -820,6 +826,9 @@ func (s *scheduler) StopJobs() error { } func (s *scheduler) Shutdown() error { + if !s.started { + return nil + } s.shutdownCancel() t := time.NewTimer(s.exec.stopTimeout + 2*time.Second) diff --git a/scheduler_test.go b/scheduler_test.go index 1a2d02d..c2b0594 100644 --- a/scheduler_test.go +++ b/scheduler_test.go @@ -567,6 +567,16 @@ func TestScheduler_Shutdown(t *testing.T) { _, err = j.NextRun() assert.ErrorIs(t, err, ErrJobNotFound) }) + + t.Run("calling shutdown multiple times including before start is a no-op", func(t *testing.T) { + s := newTestScheduler(t) + + assert.NoError(t, s.Shutdown()) + s.Start() + + assert.NoError(t, s.Shutdown()) + assert.NoError(t, s.Shutdown()) + }) } func TestScheduler_NewJob(t *testing.T) {