or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

configuration-options.mdcore-scheduler.mdindex.mdjob-management.mdjob-wrappers.mdlogging.mdschedule-parsing.mdschedule-types.md
tile.json

core-scheduler.mddocs/

Core Scheduler

The core scheduler manages the lifecycle of cron jobs, including starting, stopping, and running jobs on their configured schedules.

Creating a Scheduler

// New creates a new Cron job runner with optional configuration.
// Returns a scheduler with default settings if no options are provided.
//
// Available Settings:
//   - Time Zone: Defaults to time.Local
//   - Parser: Defaults to standard 5-field cron spec
//   - Chain: Defaults to a chain that recovers panics
//   - Logger: Defaults to DefaultLogger
func New(opts ...Option) *Cron

Type Definitions:

type Cron struct {
    // contains unexported fields
}

type Option func(*Cron)

Usage

import (
    "time"
    "github.com/robfig/cron/v3"
)

// Basic scheduler with defaults
c := cron.New()

// Scheduler with custom timezone
nyc, _ := time.LoadLocation("America/New_York")
c := cron.New(cron.WithLocation(nyc))

// Scheduler with seconds field in cron specs
c := cron.New(cron.WithSeconds())

// Scheduler with multiple options
c := cron.New(
    cron.WithLocation(nyc),
    cron.WithSeconds(),
    cron.WithLogger(cron.VerbosePrintfLogger(log.New(os.Stdout, "cron: ", log.LstdFlags))),
)

Starting the Scheduler

Asynchronous Start

// Start begins the scheduler in its own goroutine.
// This is a no-op if the scheduler is already running.
func (c *Cron) Start()

Usage:

c := cron.New()

// Add jobs before starting
c.AddFunc("@hourly", func() { fmt.Println("Job 1") })

// Start in background
c.Start()

// Can continue adding jobs while running
c.AddFunc("@daily", func() { fmt.Println("Job 2") })

// Main program continues...

Synchronous Run

// Run starts the scheduler synchronously (blocking).
// This is a no-op if the scheduler is already running.
// The calling goroutine will be blocked until Stop() is called.
func (c *Cron) Run()

Usage:

c := cron.New()
c.AddFunc("@every 5s", func() { fmt.Println("Running") })

// This blocks until Stop() is called
c.Run()

Stopping the Scheduler

// Stop stops the scheduler if running; otherwise does nothing.
// A context is returned so the caller can wait for running jobs to complete.
// The scheduler can be restarted after stopping.
func (c *Cron) Stop() context.Context

Usage:

c := cron.New()
c.AddFunc("@every 1s", func() {
    fmt.Println("Working...")
    time.Sleep(10 * time.Second) // Long-running job
})
c.Start()

// Later: stop the scheduler
ctx := c.Stop()

// Wait for all jobs to complete
<-ctx.Done()
fmt.Println("All jobs finished")

Complete Example

package main

import (
    "context"
    "fmt"
    "time"
    "github.com/robfig/cron/v3"
)

func main() {
    // Create scheduler with verbose logging
    c := cron.New(
        cron.WithLogger(cron.VerbosePrintfLogger(
            log.New(os.Stdout, "cron: ", log.LstdFlags),
        )),
    )

    // Add jobs
    c.AddFunc("*/5 * * * *", func() {
        fmt.Println("Every 5 minutes")
    })

    c.AddFunc("0 0 * * *", func() {
        fmt.Println("Daily at midnight")
    })

    // Start scheduler
    c.Start()
    fmt.Println("Scheduler started")

    // Run for a while
    time.Sleep(1 * time.Hour)

    // Stop and wait for jobs to finish
    fmt.Println("Stopping scheduler...")
    ctx := c.Stop()

    // Wait up to 30 seconds for jobs to complete
    waitCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
    defer cancel()

    select {
    case <-ctx.Done():
        fmt.Println("All jobs completed")
    case <-waitCtx.Done():
        fmt.Println("Timeout waiting for jobs to complete")
    }
}

Thread Safety

All Cron methods (Start, Stop, AddFunc, AddJob, Schedule, Remove, Entries, Entry) are designed to be thread-safe. The caller must ensure invocations have a clear happens-before ordering between them, but concurrent access from multiple goroutines is safe.

Scheduler Behavior

Initialization

  • When created with New(), the scheduler is in a stopped state
  • Jobs can be added before starting
  • The scheduler begins processing when Start() or Run() is called

Running State

  • Jobs are executed in separate goroutines when their schedules activate
  • Multiple jobs can run concurrently
  • Jobs added while running are immediately scheduled
  • Next run times are calculated after each execution

Stopped State

  • Calling Stop() prevents new job executions
  • Already-running jobs continue until completion
  • The returned context signals when all jobs have finished
  • The scheduler can be restarted with Start() or Run()

Sleep and Wake Cycle

The scheduler:

  1. Sorts entries by next activation time
  2. Sleeps until the next job is due
  3. Wakes up and runs all jobs due at that time
  4. Recalculates next run times
  5. Repeats

If no entries are scheduled, the scheduler sleeps indefinitely until a new entry is added or it's stopped.