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

timing.mddocs/api/options/

Timing Options

Options for controlling when jobs start and stop.

WithStartAt

func WithStartAt(option StartAtOption) JobOption

Controls first execution time. Options:

func WithStartImmediately() StartAtOption
func WithStartDateTime(start time.Time) StartAtOption
func WithStartDateTimePast(start time.Time) StartAtOption

WithStartImmediately

Runs job immediately when scheduler starts (or when NewJob called if already running). After immediate run, follows normal schedule.

// Daily at 9 AM, but run immediately on startup
j, _ := s.NewJob(
    gocron.DailyJob(1, gocron.NewAtTimes(gocron.NewAtTime(9, 0, 0))),
    gocron.NewTask(doMorningTask),
    gocron.WithStartAt(gocron.WithStartImmediately()),
)

WithStartDateTime

Sets first execution to specific future time. Must be in future (relative to scheduler clock).

Errors:

  • ErrWithStartDateTimePast: time is in past
  • ErrWithStartDateTimePastZero: time is zero
  • ErrStartTimeLaterThanEndTime: start is after already-set stop time
// Daily at 9 AM, starting tomorrow
tomorrow9AM := time.Now().Add(24*time.Hour).Truncate(24*time.Hour).Add(9*time.Hour)
j, _ := s.NewJob(
    gocron.DailyJob(1, gocron.NewAtTimes(gocron.NewAtTime(9, 0, 0))),
    gocron.NewTask(doMorningTask),
    gocron.WithStartAt(gocron.WithStartDateTime(tomorrow9AM)),
)

WithStartDateTimePast

Like WithStartDateTime but allows past times. Scheduler computes next run from start forward.

Use case: Backdate schedule to align with calendar boundary (e.g., weekly job from last Monday for proper alignment).

Errors:

  • ErrWithStartDateTimePastZero: time is zero
// Weekly Monday at 9 AM, backdated to last Monday
lastMonday := time.Now().AddDate(0, 0, -7)
j, _ := s.NewJob(
    gocron.WeeklyJob(
        1,
        gocron.NewWeekdays(time.Monday),
        gocron.NewAtTimes(gocron.NewAtTime(9, 0, 0)),
    ),
    gocron.NewTask(doWeeklyReport),
    gocron.WithStartAt(gocron.WithStartDateTimePast(lastMonday)),
)
// Runs next Monday at 9 AM

WithStopAt

func WithStopAt(option StopAtOption) JobOption

Sets time after which job no longer runs.

func WithStopDateTime(end time.Time) StopAtOption

Parameters:

  • end: Must be in future and not before start time (if set)

Errors:

  • ErrWithStopDateTimePast: end is in past or zero
  • ErrStopTimeEarlierThanStartTime: end is before start
// Run for 24 hours
end := time.Now().Add(24 * time.Hour)
j, _ := s.NewJob(
    gocron.DurationJob(time.Minute),
    gocron.NewTask(myFunc),
    gocron.WithStopAt(gocron.WithStopDateTime(end)),
)

// Run daily for one week
weekFromNow := time.Now().AddDate(0, 0, 7)
j, _ = s.NewJob(
    gocron.DailyJob(1, gocron.NewAtTimes(gocron.NewAtTime(9, 0, 0))),
    gocron.NewTask(doTask),
    gocron.WithStopAt(gocron.WithStopDateTime(weekFromNow)),
)

WithLimitedRuns

func WithLimitedRuns(limit uint) JobOption

Limits job to run at most N times, then automatically removes it.

Parameters:

  • limit: Must be > 0

Errors:

  • ErrWithLimitedRunsZero: limit is 0
// Run exactly 3 times then stop
j, _ := s.NewJob(
    gocron.DurationJob(time.Minute),
    gocron.NewTask(myFunc),
    gocron.WithLimitedRuns(3),
)
// Runs at: 0, 60s, 120s, then removed

Uses:

  • Temporary jobs (retry with max attempts)
  • Migration jobs (run once per deployment instance)
  • Warmup/initialization (run N times on startup)

Note: Skipped runs (due to singleton mode or concurrency limits) don't count. Only actual executions count.

WithContext

func WithContext(ctx context.Context) JobOption

Sets parent context for the job. gocron creates a child context and injects it as the first argument if task function accepts context.Context as first parameter.

Parameters:

  • ctx: Must not be nil

Errors:

  • ErrWithContextNil: ctx is nil

Context cancellation:

  • Scheduler shutdown
  • Parent context cancellation (also stops job scheduling)
ctx, cancel := context.WithCancel(context.Background())

j, _ := s.NewJob(
    gocron.DurationJob(time.Minute),
    gocron.NewTask(func(ctx context.Context) {
        select {
        case <-ctx.Done():
            log.Println("Context cancelled")
            return
        default:
            doWork()
        }
    }),
    gocron.WithContext(ctx),
)

// Later: cancel() stops job scheduling and cancels running job
cancel()

Context injection: Automatic if first parameter is context.Context. Don't pass context via NewTask parameters.

// CORRECT: context auto-injected
task := gocron.NewTask(func(ctx context.Context, msg string) {
    fmt.Println(msg)
}, "hello")

// INCORRECT: don't pass context manually
// task := gocron.NewTask(func(ctx context.Context) { ... }, myContext)

Uses:

  • Graceful cancellation
  • Scoped contexts (per-tenant, per-request)
  • Timeouts (wrap with context.WithTimeout)
  • Tracing/logging (context-based loggers)

Usage Examples

Start Immediately

j, _ := s.NewJob(
    gocron.DailyJob(1, gocron.NewAtTimes(gocron.NewAtTime(9, 0, 0))),
    gocron.NewTask(func() {
        log.Println("Running daily task")
    }),
    gocron.WithStartAt(gocron.WithStartImmediately()),
)
// Runs immediately, then daily at 9 AM

Start at Specific Time

launchTime := time.Date(2024, 3, 15, 10, 0, 0, 0, time.Local)
j, _ := s.NewJob(
    gocron.DurationJob(time.Hour),
    gocron.NewTask(func() {
        checkStatus()
    }),
    gocron.WithStartAt(gocron.WithStartDateTime(launchTime)),
)
// First run at launch time, then hourly

Limited Time Window

start := time.Now()
end := start.Add(24 * time.Hour)

j, _ := s.NewJob(
    gocron.DurationJob(5*time.Minute),
    gocron.NewTask(func() {
        monitorSystem()
    }),
    gocron.WithStartAt(gocron.WithStartDateTime(start)),
    gocron.WithStopAt(gocron.WithStopDateTime(end)),
)
// Runs every 5 minutes for 24 hours

Retry with Limit

j, _ := s.NewJob(
    gocron.DurationJob(10*time.Second),
    gocron.NewTask(func() error {
        return attemptOperation()
    }),
    gocron.WithLimitedRuns(5), // Try up to 5 times
    gocron.WithEventListeners(
        gocron.AfterJobRuns(func(jobID uuid.UUID, jobName string) {
            log.Println("Operation succeeded")
        }),
    ),
)

Context with Timeout

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
defer cancel()

j, _ := s.NewJob(
    gocron.DurationJob(time.Minute),
    gocron.NewTask(func(ctx context.Context) error {
        select {
        case <-ctx.Done():
            return ctx.Err()
        default:
            return doWork()
        }
    }),
    gocron.WithContext(ctx),
)
// Jobs timeout after 5 minutes total

Campaign Schedule

campaignStart := time.Date(2024, 3, 1, 0, 0, 0, 0, time.Local)
campaignEnd := time.Date(2024, 3, 31, 23, 59, 59, 0, time.Local)

j, _ := s.NewJob(
    gocron.DailyJob(1, gocron.NewAtTimes(
        gocron.NewAtTime(9, 0, 0),
        gocron.NewAtTime(15, 0, 0),
        gocron.NewAtTime(20, 0, 0),
    )),
    gocron.NewTask(func() {
        sendCampaignEmail()
    }),
    gocron.WithStartAt(gocron.WithStartDateTime(campaignStart)),
    gocron.WithStopAt(gocron.WithStopDateTime(campaignEnd)),
)
// Sends emails 3x daily for entire month

Combining Options

All timing options can be combined:

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

start := time.Now().Add(1 * time.Hour)
end := time.Now().Add(25 * time.Hour)

j, _ := s.NewJob(
    gocron.DurationJob(5*time.Minute),
    gocron.NewTask(func(ctx context.Context) {
        performTask()
    }),
    gocron.WithContext(ctx),
    gocron.WithStartAt(gocron.WithStartDateTime(start)),
    gocron.WithStopAt(gocron.WithStopDateTime(end)),
    gocron.WithLimitedRuns(100),
)
// Starts in 1 hour, runs for 24 hours, max 100 times

See Also

  • Identity Options - Naming and tagging
  • Concurrency Options - Execution control
  • Event Listeners - Callbacks
  • One-Time Jobs - Single execution
  • Lifecycle Guide - Job lifecycle management

Install with Tessl CLI

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

docs

api

errors.md

quick-reference.md

tasks.md

index.md

tile.json