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.
Practical examples of implementing gocron interfaces.
package main
import (
"fmt"
"log"
"os"
"time"
"github.com/go-co-op/gocron/v2"
)
type customLogger struct {
logger *log.Logger
}
func newCustomLogger() *customLogger {
return &customLogger{
logger: log.New(os.Stdout, "", log.LstdFlags),
}
}
func (l *customLogger) Debug(msg string, args ...any) {
l.logger.Printf("[DEBUG] "+msg, args...)
}
func (l *customLogger) Error(msg string, args ...any) {
l.logger.Printf("[ERROR] "+msg, args...)
}
func (l *customLogger) Info(msg string, args ...any) {
l.logger.Printf("[INFO] "+msg, args...)
}
func (l *customLogger) Warn(msg string, args ...any) {
l.logger.Printf("[WARN] "+msg, args...)
}
func main() {
s, _ := gocron.NewScheduler(
gocron.WithLogger(newCustomLogger()),
)
defer s.Shutdown()
s.NewJob(
gocron.DurationJob(time.Second),
gocron.NewTask(func() {
fmt.Println("Working...")
}),
)
s.Start()
time.Sleep(5 * time.Second)
}import (
"github.com/google/uuid"
)
type customMonitor struct {
executions map[string]int
durations map[string][]time.Duration
}
func newCustomMonitor() *customMonitor {
return &customMonitor{
executions: make(map[string]int),
durations: make(map[string][]time.Duration),
}
}
func (m *customMonitor) RecordJobTiming(
start time.Time,
duration time.Duration,
jobID uuid.UUID,
jobName string,
tags []string,
) {
m.executions[jobName]++
m.durations[jobName] = append(m.durations[jobName], duration)
fmt.Printf("Job %s: execution #%d took %v\n",
jobName, m.executions[jobName], duration)
}
func (m *customMonitor) GetStats(jobName string) (int, time.Duration) {
count := m.executions[jobName]
durations := m.durations[jobName]
if len(durations) == 0 {
return count, 0
}
var total time.Duration
for _, d := range durations {
total += d
}
return count, total / time.Duration(len(durations))
}
func main() {
monitor := newCustomMonitor()
s, _ := gocron.NewScheduler(
gocron.WithMonitor(monitor),
)
defer s.Shutdown()
s.NewJob(
gocron.DurationJob(time.Second),
gocron.NewTask(func() {
time.Sleep(100 * time.Millisecond)
}),
gocron.WithName("worker"),
)
s.Start()
time.Sleep(5 * time.Second)
count, avgDuration := monitor.GetStats("worker")
fmt.Printf("Stats: %d executions, avg duration: %v\n", count, avgDuration)
}type customSchedulerMonitor struct {
startTimes map[uuid.UUID]time.Time
}
func newCustomSchedulerMonitor() *customSchedulerMonitor {
return &customSchedulerMonitor{
startTimes: make(map[uuid.UUID]time.Time),
}
}
func (m *customSchedulerMonitor) JobScheduled(jobID uuid.UUID, job gocron.Job) {
fmt.Printf("[SCHEDULED] %s (ID: %s)\n", job.Name(), jobID)
}
func (m *customSchedulerMonitor) JobUnscheduled(jobID uuid.UUID, job gocron.Job) {
fmt.Printf("[UNSCHEDULED] %s (ID: %s)\n", job.Name(), jobID)
}
func (m *customSchedulerMonitor) JobStarted(jobID uuid.UUID, job gocron.Job) {
m.startTimes[jobID] = time.Now()
fmt.Printf("[STARTED] %s at %v\n", job.Name(), m.startTimes[jobID])
}
func (m *customSchedulerMonitor) JobCompleted(jobID uuid.UUID, job gocron.Job, err error) {
duration := time.Since(m.startTimes[jobID])
if err != nil {
fmt.Printf("[FAILED] %s after %v: %v\n", job.Name(), duration, err)
} else {
fmt.Printf("[COMPLETED] %s in %v\n", job.Name(), duration)
}
delete(m.startTimes, jobID)
}
func (m *customSchedulerMonitor) ConcurrencyLimitReached(limitType string, job gocron.Job) {
fmt.Printf("[LIMIT] %s concurrency limit reached for %s\n", limitType, job.Name())
}
func main() {
s, _ := gocron.NewScheduler(
gocron.WithSchedulerMonitor(newCustomSchedulerMonitor()),
)
defer s.Shutdown()
s.NewJob(
gocron.DurationJob(time.Second),
gocron.NewTask(func() error {
time.Sleep(500 * time.Millisecond)
return nil
}),
gocron.WithName("monitored-job"),
)
s.Start()
time.Sleep(5 * time.Second)
}Install with Tessl CLI
npx tessl i tessl/golang-github-com-go-co-op-gocron-v2docs
api
examples
guides