Gracefull stop cronjob
Hey team, I have problem with stop cron job. When I stop server while the job is running, it will be force close my job. I want to Gracefull stop the job Does have any solution for this?
Version
- go 1.24.2
- github.com/robfig/cron v1.2.0
Code sample
package main
import (
"fmt"
"os"
"os/signal"
"sync"
"syscall"
"time"
"github.com/robfig/cron"
)
var (
cronJob *cron.Cron
startOnce sync.Once
stopOnce sync.Once
)
func StartCronJobs() {
startOnce.Do(func() {
fmt.Println("[StartCronJobs] start cronjob")
cronJob = cron.New()
cronJob.Start()
cronJob.AddFunc("@every 10s", func() {
fmt.Println("Cron job running at", time.Now())
TestJob()
fmt.Println("Cron job running completed at", time.Now())
})
})
}
func TestJob() error {
time.Sleep(7 * time.Second)
return nil
}
func StopCronJobs() {
stopOnce.Do(func() {
fmt.Println("[StopCronJobs] stop at ", time.Now())
cronJob.Stop()
fmt.Println("[StopCronJobs] stop completed at", time.Now())
})
}
func main() {
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
StartCronJobs()
<-c
fmt.Println("[Main] stop server")
StopCronJobs()
fmt.Println("[Main] stop server completed")
}
Reproduce
- Run my code
- When I run my code, when the job is running => Press Ctl +C to cancel the code
Result
[StartCronJobs] start cronjob
Cron job running at 2025-05-22 10:29:44.008364506 +0700 +07 m=+9.570125026
^C[Main] stop server
[StopCronJobs] stop at 2025-05-22 10:29:45.727787596 +0700 +07 m=+11.289548167
[StopCronJobs] stop completed at 2025-05-22 10:29:45.727830408 +0700 +07 m=+11.289590937
[Main] stop server completed
cronJob.Stop() returns a context that waits until all job are done executing
So you could wait for the job to complete using something like <-cronJob.Stop().Done()
But if you want to handle graceful stop in your job, I suggest you look at my fork which allow you to have a context directly in the job function
https://github.com/alaingilbert/cron
cronJob.AddJob("@every 10s", func(ctx context.Context) {
// you can handle graceful stop using the context
})
Solution available in maintained fork
This feature has been implemented in netresearch/go-cron, a maintained fork of this library.
Implementation:
-
JobWithContextinterface - Jobs can implementRunWithContext(ctx context.Context)to receive cancellation signals -
WithContext(ctx)option - Sets base context for all jobs -
StopWithTimeout(duration)- Graceful shutdown with configurable timeout -
StopAndWait()- Convenience method for blocking until all jobs complete
ctx, cancel := context.WithCancel(context.Background())
c := cron.New(cron.WithContext(ctx))
c.AddJob("@every 1m", cron.FuncJobWithContext(func(ctx context.Context) {
select {
case <-ctx.Done():
return // Graceful shutdown
default:
// Do work
}
}))
// Later: graceful shutdown with 30s timeout
if !c.StopWithTimeout(30 * time.Second) {
log.Println("Warning: some jobs did not complete within 30s")
}
How to migrate:
// Change import from:
import "github.com/robfig/cron/v3"
// To:
import cron "github.com/netresearch/go-cron"
The API is 100% backward compatible. See the migration guide for details.
Related: netresearch/go-cron#16, netresearch/go-cron#102, netresearch/go-cron#103