CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/golang-github-com-go-co-op-gocron-v2

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.

Overview
Eval results
Files

types.mddocs/examples/api/

Examples: Types API

Practical examples of implementing gocron interfaces.

Custom Logger

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)
}

Custom Monitor

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)
}

Custom Scheduler Monitor

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)
}

See Also

  • Types API Guide
  • Observability Examples

Install with Tessl CLI

npx tessl i tessl/golang-github-com-go-co-op-gocron-v2

docs

index.md

tile.json