A Golang job scheduling library that lets you run Go functions at pre-determined intervals using cron expressions, fixed durations, daily, weekly, monthly, or one-time schedules with support for distributed deployments.
A cheat sheet for common gocron v2 operations.
import "github.com/go-co-op/gocron/v2"
s, err := gocron.NewScheduler()
if err != nil {
panic(err)
}
defer s.Shutdown()
j, err := s.NewJob(
gocron.DurationJob(5*time.Minute),
gocron.NewTask(func() { fmt.Println("Working") }),
)
s.Start()// Every 5 minutes
gocron.DurationJob(5 * time.Minute)
// Random 4-6 minutes
gocron.DurationRandomJob(4*time.Minute, 6*time.Minute)
// Cron: every 5 minutes
gocron.CronJob("*/5 * * * *", false)
// Daily at 9 AM
gocron.DailyJob(1, gocron.NewAtTimes(
gocron.NewAtTime(9, 0, 0),
))
// Monday at 9 AM
gocron.WeeklyJob(1,
gocron.NewWeekdays(time.Monday),
gocron.NewAtTimes(gocron.NewAtTime(9, 0, 0)),
)
// 1st of month at noon
gocron.MonthlyJob(1,
gocron.NewDaysOfTheMonth(1),
gocron.NewAtTimes(gocron.NewAtTime(12, 0, 0)),
)
// Run once immediately
gocron.OneTimeJob(gocron.OneTimeJobStartImmediately())// Set timezone
loc, _ := time.LoadLocation("America/Chicago")
gocron.WithLocation(loc)
// Logging
gocron.WithLogger(gocron.NewLogger(gocron.LogLevelInfo))
// Graceful shutdown timeout
gocron.WithStopTimeout(30 * time.Second)
// Limit concurrent jobs (reschedule if full)
gocron.WithLimitConcurrentJobs(5, gocron.LimitModeReschedule)
// Global job options
gocron.WithGlobalJobOptions(
gocron.WithTags("production"),
)// Name
gocron.WithName("cleanup-job")
// Tags
gocron.WithTags("worker", "cleanup")
// Prevent concurrent runs
gocron.WithSingletonMode(gocron.LimitModeReschedule)
// Interval from completion
gocron.WithIntervalFromCompletion()
// Run N times then stop
gocron.WithLimitedRuns(10)
// Start immediately
gocron.WithStartAt(gocron.WithStartImmediately())
// Stop after time
gocron.WithStopAt(gocron.WithStopDateTime(endTime))
// Custom context
gocron.WithContext(ctx)// No parameters
gocron.NewTask(func() {
doWork()
})
// With parameters
gocron.NewTask(func(msg string, n int) {
fmt.Printf("%s: %d\n", msg, n)
}, "Count", 42)
// Auto-injected context
gocron.NewTask(func(ctx context.Context) {
select {
case <-ctx.Done():
return
default:
doWork()
}
})
// Context with parameters
gocron.NewTask(func(ctx context.Context, msg string) {
fmt.Println(msg)
}, "Hello")
// Return error
gocron.NewTask(func() error {
return doWorkWithError()
})gocron.WithEventListeners(
gocron.BeforeJobRuns(func(jobID uuid.UUID, jobName string) {
log.Printf("Starting %s", jobName)
}),
gocron.AfterJobRuns(func(jobID uuid.UUID, jobName string) {
log.Printf("Completed %s", jobName)
}),
gocron.AfterJobRunsWithError(func(jobID uuid.UUID, jobName string, err error) {
log.Printf("Failed %s: %v", jobName, err)
}),
gocron.AfterJobRunsWithPanic(func(jobID uuid.UUID, jobName string, recoverData any) {
log.Printf("Panicked %s: %v", jobName, recoverData)
}),
)// Update job
j, err = s.Update(
j.ID(),
gocron.DurationJob(10*time.Minute),
gocron.NewTask(myFunc),
gocron.WithName("updated-job"),
)
// Remove by ID
s.RemoveJob(j.ID())
// Remove by tags (all with ALL specified tags)
s.RemoveByTags("cleanup")
s.RemoveByTags("worker", "low-priority")
// List all jobs
for _, job := range s.Jobs() {
fmt.Printf("%s: next at %v\n", job.Name(), job.NextRun())
}
// Trigger immediate run
j.RunNow()
// Job info
id := j.ID()
name := j.Name()
tags := j.Tags()
lastRun, _ := j.LastRun()
nextRun, _ := j.NextRun()
nextFive, _ := j.NextRuns(5)// Start scheduler
s.Start()
// Pause (no new runs, existing continue)
s.StopJobs()
// Resume after pause
s.Start()
// Graceful shutdown
err := s.Shutdown()
if errors.Is(err, gocron.ErrStopSchedulerTimedOut) {
log.Println("Timeout waiting for jobs")
}
// Check queue size
queueSize := s.JobsWaitingInQueue()// Leader election (only leader runs jobs)
gocron.WithDistributedElector(elector)
// Distributed locking (per-job coordination)
gocron.WithDistributedLocker(locker)
// Per-job locker
gocron.WithDistributedJobLocker(locker)
// Disable global locker for job
gocron.WithDisabledDistributedJobLocker(true)// Basic metrics
gocron.WithMonitor(&myMonitor{})
// Metrics with status
gocron.WithMonitorStatus(&myMonitorStatus{})
// Lifecycle monitoring
gocron.WithSchedulerMonitor(&mySchedulerMonitor{})Install with Tessl CLI
npx tessl i tessl/golang-github-com-go-co-op-gocron-v2@2.19.1docs
api
examples
guides