cron

package module
v1.8.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 13, 2026 License: BSD-2-Clause Imports: 9 Imported by: 7

README

Cron

A Go library for robust cron job scheduling with multiple execution strategies, observability, and reliability features.

Installation

go get github.com/bborbe/cron

Quick Start

Basic Usage
package main

import (
    "context"
    "fmt"
    
    "github.com/bborbe/cron"
    "github.com/bborbe/run"
)

func main() {
    ctx := context.Background()
    
    // Create an action to run
    action := run.Func(func(ctx context.Context) error {
        fmt.Println("Job executed!")
        return nil
    })
    
    // Expression-based scheduling
    cronJob := cron.NewCronJob(false, cron.Expression("@every 1h"), 0, action)
    cronJob.Run(ctx)
}
Enhanced Usage with Options
package main

import (
    "context"
    "time"
    
    "github.com/bborbe/cron"
    "github.com/bborbe/run"
)

func main() {
    ctx := context.Background()
    
    action := run.Func(func(ctx context.Context) error {
        // Your job logic here
        return nil
    })
    
    // Configure options
    options := cron.CronJobOptions{
        Name:          "my-important-job",
        EnableMetrics: true,
        Timeout:       5 * time.Minute,
        ParallelSkip:  true,
    }
    
    // Create job with options
    cronJob := cron.NewCronJobWithOptions(
        false,                      // not one-time
        cron.Expression("0 */15 * * * ?"), // every 15 minutes
        0,                          // no wait duration
        action,
        options,
    )
    
    cronJob.Run(ctx)
}

Execution Strategies

The library automatically selects the appropriate execution strategy based on the parameters provided to NewCronJob or NewCronJobWithOptions:

1. Expression-Based (Cron Expressions)

Uses standard cron expressions or special formats:

// Every hour
cronJob := cron.NewCronJob(false, cron.Expression("@every 1h"), 0, action)

// Every 15 minutes using cron syntax
cronJob := cron.NewCronJob(false, cron.Expression("0 */15 * * * ?"), 0, action)

// Daily at 2:30 AM
cronJob := cron.NewCronJob(false, cron.Expression("0 30 2 * * ?"), 0, action)
2. Duration-Based (Intervals)

Uses Go time.Duration for simple intervals:

// Every 30 seconds
cronJob := cron.NewCronJob(false, "", 30*time.Second, action)

// Every 5 minutes
cronJob := cron.NewCronJob(false, "", 5*time.Minute, action)
3. One-Time Execution

Executes the job once immediately:

// Run once
cronJob := cron.NewCronJob(true, "", 0, action)

Configuration Options

The CronJobOptions struct provides fine-grained control over job behavior:

type CronJobOptions struct {
    Name          string        // Job name for metrics and logging
    EnableMetrics bool          // Enable Prometheus metrics collection  
    Timeout       time.Duration // Execution timeout (0 = disabled)
    ParallelSkip  bool          // Prevent concurrent executions
}
Default Options
options := cron.DefaultCronJobOptions()
// Returns:
// {
//     Name:          "unnamed-cron", 
//     EnableMetrics: false,
//     Timeout:       0,
//     ParallelSkip:  false,
// }

Wrapper Functions

For maximum flexibility, you can use wrapper functions directly:

Metrics Wrapper
import "github.com/prometheus/client_golang/prometheus"

// Wrap any action with metrics
wrappedAction := cron.WrapWithMetrics("job-name", originalAction)

Metrics Collected:

  • cron_job_started{name="job-name"} - Number of job starts
  • cron_job_completed{name="job-name"} - Number of successful completions
  • cron_job_failed{name="job-name"} - Number of failures
  • cron_job_last_success{name="job-name"} - Timestamp of last success
Timeout Wrapper
// Add 5-minute timeout
wrappedAction := cron.WrapWithTimeout("job-name", 5*time.Minute, originalAction)

// Disable timeout (≤0 duration)
wrappedAction := cron.WrapWithTimeout("job-name", 0, originalAction)
Chaining Wrappers
// Chain multiple wrappers (order matters)
action := cron.WrapWithTimeout("my-job", 5*time.Minute, originalAction)
action = cron.WrapWithMetrics("my-job", action)

Monitoring and Observability

Prometheus Integration

When metrics are enabled, the library automatically registers Prometheus collectors. Expose them via HTTP:

import (
    "net/http"
    "github.com/prometheus/client_golang/prometheus/promhttp"
)

func main() {
    // Your cron jobs with EnableMetrics: true
    
    // Expose metrics endpoint
    http.Handle("/metrics", promhttp.Handler())
    http.ListenAndServe(":8080", nil)
}
Custom Metrics

Access the metrics interface directly:

metrics := cron.NewCronMetrics()
metrics.IncreaseStarted("custom-job")
metrics.IncreaseCompleted("custom-job") 
metrics.SetLastSuccessToCurrent("custom-job")

Error Handling

The library provides proper error propagation through all wrapper layers:

action := run.Func(func(ctx context.Context) error {
    return errors.New("job failed")
})

cronJob := cron.NewCronJobWithOptions(true, "", 0, action, options)
err := cronJob.Run(ctx)
if err != nil {
    // Handle error - will include context from wrappers
    log.Printf("Cron job failed: %v", err)
}

Testing

The library provides mock interfaces for testing:

//go:generate go run -mod=mod github.com/maxbrunsfeld/counterfeiter/v6 -generate

import "github.com/bborbe/cron/mocks"

func TestMyCronJob(t *testing.T) {
    mockCronJob := &mocks.CronJob{}
    mockMetrics := &mocks.CronMetrics{}
    
    // Set up expectations and test your code
}

Examples

Web Scraper with Monitoring
options := cron.CronJobOptions{
    Name:          "web-scraper",
    EnableMetrics: true,
    Timeout:       30 * time.Second,
    ParallelSkip:  true,
}

scraper := run.Func(func(ctx context.Context) error {
    // Scrape website logic
    return scrapeWebsite(ctx)
})

cronJob := cron.NewCronJobWithOptions(
    false,
    cron.Expression("0 */5 * * * ?"), // Every 5 minutes
    0,
    scraper,
    options,
)
Database Cleanup Job
cleanup := run.Func(func(ctx context.Context) error {
    return cleanupOldRecords(ctx)
})

options := cron.CronJobOptions{
    Name:          "db-cleanup",
    EnableMetrics: true,
    Timeout:       10 * time.Minute,
}

cronJob := cron.NewCronJobWithOptions(
    false,
    cron.Expression("0 0 2 * * ?"), // Daily at 2 AM
    0,
    cleanup,
    options,
)

License

BSD-style license. See LICENSE file for details.

Documentation

Overview

Package cron provides scheduling functionality for executing tasks at specified intervals.

This library offers three execution strategies:

  • Expression-based scheduling using cron expressions (e.g., "@every 1h", "0 */15 * * * ?")
  • Duration-based intervals for repeated execution at fixed time intervals
  • One-time execution for tasks that should run only once

The package includes configurable options for timeouts, metrics collection, and parallel execution control. All schedulers support graceful context-based cancellation.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CreateDefaultParser added in v1.2.0

func CreateDefaultParser() cron.Parser

CreateDefaultParser creates a cron expression parser with second-level precision. The parser supports the standard cron format with optional seconds field.

func NewCronJob

func NewCronJob(
	oneTime bool,
	expression Expression,
	wait libtime.Duration,
	action run.Runnable,
) run.Runnable

NewCronJob creates a new cron job with automatic strategy selection based on parameters. Uses one-time execution if oneTime is true, expression-based scheduling if expression is provided, or duration-based intervals if wait duration is specified.

func NewCronJobWithOptions added in v1.4.0

func NewCronJobWithOptions(
	oneTime bool,
	expression Expression,
	wait libtime.Duration,
	action run.Runnable,
	options Options,
) run.Runnable

NewCronJobWithOptions creates a new cron job with configurable options. Applies the same strategy selection as NewCronJob but with additional wrappers for timeout, metrics, and parallel execution control based on the provided options.

func NewExpressionCron

func NewExpressionCron(
	expression Expression,
	action run.Runnable,
) run.Runnable

NewExpressionCron creates a cron job that executes based on a cron expression. The expression supports standard cron format and common descriptors like '@every 1h'.

func NewExpressionCronWithOptions added in v1.5.0

func NewExpressionCronWithOptions(
	expression Expression,
	action run.Runnable,
	options Options,
) run.Runnable

NewExpressionCronWithOptions creates an expression-based cron job with configurable options. Applies timeout, metrics, and parallel execution controls to individual action executions.

func NewIntervalCron added in v1.3.1

func NewIntervalCron(
	wait libtime.Duration,
	action run.Runnable,
) run.Runnable

NewIntervalCron creates a cron job that executes at fixed time intervals. The job runs continuously with the specified wait duration between executions.

func NewIntervalCronWithOptions added in v1.5.0

func NewIntervalCronWithOptions(
	wait libtime.Duration,
	action run.Runnable,
	options Options,
) run.Runnable

NewIntervalCronWithOptions creates an interval-based cron job with configurable options. Applies timeout, metrics, and parallel execution controls to individual action executions.

func NewOneTimeCron

func NewOneTimeCron(
	action run.Runnable,
) run.Runnable

NewOneTimeCron creates a cron job that executes only once. The job completes after a single execution of the provided action.

func NewOneTimeCronWithOptions added in v1.5.0

func NewOneTimeCronWithOptions(
	action run.Runnable,
	options Options,
) run.Runnable

NewOneTimeCronWithOptions creates a one-time cron job with configurable options. Applies timeout, metrics, and parallel execution controls to the single action execution.

func NewWaitCron

func NewWaitCron(
	wait libtime.Duration,
	action run.Runnable,
) run.Runnable

NewWaitCron Deprecated: use NewIntervalCron instead

func WrapWithMetrics added in v1.4.0

func WrapWithMetrics(name string, fn run.Runnable) run.Runnable

WrapWithMetrics wraps a runnable with Prometheus metrics collection. Records start, completion, failure counts and execution duration for the named job.

func WrapWithOptions added in v1.5.0

func WrapWithOptions(action run.Runnable, options Options) run.Runnable

WrapWithOptions applies all configured wrappers to an action based on the provided options. Wrappers are applied in this order (innermost to outermost): 1. Timeout wrapper (if timeout > 0) 2. Metrics wrapper (if enabled) 3. Parallel skip wrapper (if enabled)

func WrapWithTimeout added in v1.4.0

func WrapWithTimeout(name string, timeout libtime.Duration, fn run.Runnable) run.Runnable

WrapWithTimeout wraps a runnable with timeout enforcement. If timeout is <= 0, the original runnable is returned unchanged. Otherwise, executions are cancelled if they exceed the specified duration.

Types

type Cron

type Cron interface {
	// Run executes the cron job until the context is cancelled or an error occurs.
	// For recurring jobs, this method blocks and continues scheduling executions.
	// For one-time jobs, this method returns after a single execution.
	Run(ctx context.Context) error
}

Cron represents a scheduled task that can be executed with context-based cancellation.

type Expression added in v1.2.0

type Expression string

Expression of the cron cron.Second | cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow | cron.Descriptor every second: * * * * * ? every minute 0 * * * * ? every 15 minute 0 */15 * * * ? every hour: 0 0 * * * ? every hour on sunday: 0 0 * * * 0

func (Expression) Bytes added in v1.2.0

func (e Expression) Bytes() []byte

Bytes returns the cron expression as a byte slice.

func (Expression) Ptr added in v1.2.0

func (e Expression) Ptr() *Expression

Ptr returns a pointer to the Expression value.

func (Expression) String added in v1.2.0

func (e Expression) String() string

String returns the cron expression as a string.

type Metrics added in v1.4.0

type Metrics interface {
	// IncreaseStarted increments the counter for cron job start events.
	IncreaseStarted(name string)
	// IncreaseFailed increments the counter for cron job failure events.
	IncreaseFailed(name string)
	// IncreaseCompleted increments the counter for cron job completion events.
	IncreaseCompleted(name string)
	// SetLastSuccessToCurrent records the timestamp of the last successful execution.
	SetLastSuccessToCurrent(name string)
	// ObserveDuration records the execution duration in seconds for the named cron job.
	ObserveDuration(name string, durationSeconds float64)
}

Metrics provides methods for collecting and reporting cron job execution statistics.

func NewMetrics added in v1.4.0

func NewMetrics() Metrics

NewMetrics creates a new Metrics instance that reports to Prometheus.

type Options added in v1.5.1

type Options struct {
	// Name identifies the cron job for logging and metrics.
	Name string
	// EnableMetrics enables duration and execution metrics collection.
	EnableMetrics bool
	// Timeout sets the maximum duration allowed for individual action executions.
	// A value of 0 disables timeout enforcement.
	Timeout libtime.Duration
	// ParallelSkip prevents multiple instances of the same cron from running concurrently.
	ParallelSkip bool
}

Options configures behavior for cron jobs with wrappers applied.

func DefaultOptions added in v1.5.1

func DefaultOptions() Options

DefaultOptions returns a new Options with default values. The default configuration has metrics disabled, no timeout, and allows parallel execution.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL