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

advanced.mddocs/examples/guides/

Examples: Advanced Patterns

Practical examples of advanced scheduling patterns.

Timezone-Aware Scheduling

package main

import (
    "fmt"
    "time"
    "github.com/go-co-op/gocron/v2"
)

func main() {
    loc, _ := time.LoadLocation("America/New_York")

    s, _ := gocron.NewScheduler(
        gocron.WithLocation(loc),
    )
    defer s.Shutdown()

    // All jobs run in Eastern Time
    s.NewJob(
        gocron.DailyJob(1, gocron.NewAtTimes(gocron.NewAtTime(9, 0, 0))),
        gocron.NewTask(func() {
            fmt.Println("9 AM Eastern Time")
        }),
    )

    // Or use cron with specific timezone
    s.NewJob(
        gocron.CronJob("TZ=America/Los_Angeles 0 9 * * *", false),
        gocron.NewTask(func() {
            fmt.Println("9 AM Pacific Time")
        }),
    )

    s.Start()
    select {}
}

Dynamic Job Updates

func main() {
    s, _ := gocron.NewScheduler()
    defer s.Shutdown()

    j, _ := s.NewJob(
        gocron.DurationJob(time.Minute),
        gocron.NewTask(func() {
            fmt.Println("Original interval: 1 minute")
        }),
        gocron.WithName("dynamic-job"),
    )

    s.Start()

    // Update job based on condition
    go func() {
        time.Sleep(5 * time.Second)

        if shouldIncreaseInterval() {
            newJob, _ := s.Update(
                j.ID(),
                gocron.DurationJob(5*time.Minute),
                gocron.NewTask(func() {
                    fmt.Println("Updated interval: 5 minutes")
                }),
            )
            fmt.Printf("Job updated: %s\n", newJob.ID())
        }
    }()

    select {}
}

func shouldIncreaseInterval() bool {
    return true
}

Job Chaining

import "github.com/google/uuid"

func main() {
    s, _ := gocron.NewScheduler()
    defer s.Shutdown()

    var j2 gocron.Job

    // Job 1 triggers Job 2
    j1, _ := s.NewJob(
        gocron.DurationJob(time.Hour),
        gocron.NewTask(func() {
            fmt.Println("Job 1: Data collection")
            collectData()
        }),
        gocron.WithName("collector"),
        gocron.WithEventListeners(
            gocron.AfterJobRuns(func(jobID uuid.UUID, jobName string) {
                // Trigger Job 2
                j2.RunNow()
            }),
        ),
    )

    // Job 2 runs after Job 1
    j2, _ = s.NewJob(
        gocron.DurationJob(24*time.Hour),
        gocron.NewTask(func() {
            fmt.Println("Job 2: Data processing")
            processData()
        }),
        gocron.WithName("processor"),
    )

    s.Start()
    select {}
}

func collectData() {
    fmt.Println("Collecting...")
}

func processData() {
    fmt.Println("Processing...")
}

Conditional Execution

func main() {
    s, _ := gocron.NewScheduler()
    defer s.Shutdown()

    j, _ := s.NewJob(
        gocron.DurationJob(time.Minute),
        gocron.NewTask(func() {
            if shouldRun() {
                fmt.Println("Running task")
                doWork()
            } else {
                fmt.Println("Skipping task")
            }
        }),
    )

    s.Start()
    select {}
}

func shouldRun() bool {
    // Check if it's business hours
    now := time.Now()
    hour := now.Hour()
    return hour >= 9 && hour < 17 && now.Weekday() != time.Saturday && now.Weekday() != time.Sunday
}

func doWork() {
    fmt.Println("Working...")
}

Worker Pool Pattern

func main() {
    s, _ := gocron.NewScheduler(
        gocron.WithLimitConcurrentJobs(5, gocron.LimitModeReschedule),
    )
    defer s.Shutdown()

    // Create 5 worker jobs
    for i := 0; i < 5; i++ {
        workerID := i
        s.NewJob(
            gocron.DurationJob(time.Minute),
            gocron.NewTask(func() {
                item := getWorkItem()
                if item != nil {
                    fmt.Printf("Worker %d processing %v\n", workerID, item)
                    processItem(item)
                }
            }),
            gocron.WithName(fmt.Sprintf("worker-%d", workerID)),
            gocron.WithTags("worker"),
        )
    }

    s.Start()
    select {}
}

func getWorkItem() interface{} {
    // Get item from queue
    return "work-item"
}

func processItem(item interface{}) {
    fmt.Println("Processing...")
}

Retry with Backoff

func main() {
    s, _ := gocron.NewScheduler()
    defer s.Shutdown()

    j, _ := s.NewJob(
        gocron.DurationJob(time.Minute),
        gocron.NewTask(func() error {
            maxRetries := 3
            backoff := time.Second

            for attempt := 0; attempt < maxRetries; attempt++ {
                err := performOperation()
                if err == nil {
                    return nil
                }

                fmt.Printf("Attempt %d failed: %v\n", attempt+1, err)

                if attempt < maxRetries-1 {
                    time.Sleep(backoff)
                    backoff *= 2 // Exponential backoff
                }
            }

            return fmt.Errorf("failed after %d attempts", maxRetries)
        }),
        gocron.WithName("retry-job"),
        gocron.WithEventListeners(
            gocron.AfterJobRunsWithError(func(jobID uuid.UUID, jobName string, err error) {
                fmt.Printf("Job failed permanently: %v\n", err)
            }),
        ),
    )

    s.Start()
    select {}
}

func performOperation() error {
    // Simulated operation that might fail
    if time.Now().Unix()%2 == 0 {
        return fmt.Errorf("operation failed")
    }
    return nil
}

See Also

  • Advanced Scheduling Guide
  • Time-Based Scheduling Guide
  • Production Patterns Guide

Install with Tessl CLI

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

docs

index.md

tile.json