crong

package module
v0.0.0-...-66b4a19 Latest Latest
Warning

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

Go to latest
Published: Feb 26, 2024 License: AGPL-3.0 Imports: 11 Imported by: 0

README

crong

Crong: Lightweight, straightforward cron expression parser, ticker and task scheduler for your Golang projects.

Usage

Create a schedule from a cron expression, calculate future/past schedules:

package main

import (
	"fmt"
	"log"
	"time"
	"github.com/arcward/crong"
)

func main() {
	schedule, err := crong.New("0 0 * * *", time.UTC)
	if err != nil {
		log.Fatal(err)
    	}
	
	// Get the next (or most recent) scheduled time relative to the given time
	fmt.Println("Next scheduled time:", schedule.Next(time.Now()))
	fmt.Println("Previous scheduled time:", schedule.Prev(time.Now()))
    
	// Check if the given time satisfies the schedule
	if schedule.Matches(time.Now()) {
		fmt.Println("It's time!")
    	}
}

Create a ticker that sends a tick on a channel whenever the cron schedule fires, similar to time.Ticker:

package main

import (
	"context"
	"log"
	"time"
	"github.com/arcward/crong"
)

func main() {
	schedule, err := crong.New("@hourly", time.UTC)
	if err != nil {
		log.Fatal(err)
    	}
	
	ticker := crong.NewTicker(context.Background(), schedule, 1 * time.Minute)
	defer ticker.Stop()
	
	select {
	case t := <-ticker.C:
		log.Printf("%s: Tick!", t)
    	}
}

Schedule a function to run whenever the schedule fires:

package main

import (
	"context"
	"log"
	"time"
	"github.com/arcward/crong"
)

func main() {
	schedule, err := crong.New("* * * * *", time.UTC)
	if err != nil {
		log.Fatal(err)
    	}
	
	// MaxConcurrent=0 only allows the job to run sequentially, while
	// increasing TickerReceiveTimeout can accommodate potentially long-running
	// jobs, where you may not want the next tick to be dropped immediately.
	// MaxConsecutiveFailures=10 will stop executing the given function if it
	// returns a non-nil error ten times in a row.
	opts := &crong.ScheduledJobOptions{
		MaxConcurrent:        0,
		TickerReceiveTimeout: 30 * time.Second,
		MaxConsecutiveFailures: 10,
	}
	scheduledJob := crong.ScheduleFunc(
		context.Background(),
		schedule,
		opts,
		func(t time.Time) error {
			log.Printf("Scheduled run for %s started at %s", t, time.Now())
			return nil
        	},
	)
	defer scheduledJob.Stop(context.Background())
}

Syntax

Supports standard cron syntax (see https://en.wikipedia.org/wiki/Cron), as well as less standard expressions. For example, 5/10 4,5 * * means "every 10 minutes starting at the 5th minute of the hour, for hours 4 and 5."

Days of the week are indexed 0-6, with 0 being Sunday, and can be referenced by name (SUN, MON, TUE, WED, THU, FRI, SAT) or by number.

Months are indexed 1-12, and can be referenced by name (JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC) or by number.

Cron macros supported:

  • @yearly (or @annually) - Run once a year, midnight, Jan. 1
  • @monthly - Run once a month, midnight, first of month
  • @weekly - Run once a week, midnight between Saturday and Sunday
  • @daily (or @midnight) - Run once a day, midnight
  • @hourly - Run once an hour, beginning of hour

Other characters supported:

  • *: Wildcard/Any value (ex: Every minute: * * * * *)
  • ,: Value list separator (ex: Minute 0 and 30 of every hour: 0,30 * * * *)
  • -: Range of values (ex: Minute 0-15 of every hour: 0-15 * * * *)
  • /: Step values (ex: Every 2nd minute from minute 10-20 of every hour: 10-20/2 * * * *)
  • ?: No specific value (month, day of month, day of week only)
  • L: Last day of month. When used, must be used alone in the day field (ex: 12:30 on the last day of every month: 30 12 L * *)

Documentation

Overview

Package crong is a library for parsing cron expressions, calculating the next run times of the expressions, and validating the expressions.

Syntax

Supports standard cron syntax (see https://en.wikipedia.org/wiki/Cron), as well as less standard expressions. For example, `5/10 4,5 * *` means "every 10 minutes starting at the 5th minute of the hour, for hours 4 and 5."

Days of the week are indexed 0-6, with 0 being Sunday, and can be referenced by name (SUN, MON, TUE, WED, THU, FRI, SAT) or by number.

Months are indexed 1-12, and can be referenced by name (JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC) or by number.

Cron macros supported:

@yearly (or @annually) - Run once a year, midnight, Jan. 1
@monthly - Run once a month, midnight, first of month
@weekly - Run once a week, midnight between Saturday and Sunday
@daily (or @midnight) - Run once a day, midnight
@hourly - Run once an hour, beginning of hour

Other characters supported:

  • - any value , - value list separator
  • - range of values / - step values ? - no specific value (month, day of month, day of week only) L - last day of month (when used, must be used alone)

Index

Constants

View Source
const (
	Any           = '*'
	ListSeparator = ','
	Range         = '-'
	Step          = '/'
	Blank         = '?'
	Last          = 'L'

	Yearly   = "@yearly"
	Annually = "@annually"
	Monthly  = "@monthly"
	Weekly   = "@weekly"
	Daily    = "@daily"
	Midnight = "@midnight"
	Hourly   = "@hourly"

	Sunday    = "SUN"
	Monday    = "MON"
	Tuesday   = "TUE"
	Wednesday = "WED"
	Thursday  = "THU"
	Friday    = "FRI"
	Saturday  = "SAT"

	January   = "JAN"
	February  = "FEB"
	March     = "MAR"
	April     = "APR"
	May       = "MAY"
	June      = "JUN"
	July      = "JUL"
	August    = "AUG"
	September = "SEP"
	October   = "OCT"
	November  = "NOV"
	December  = "DEC"
)

Variables

This section is empty.

Functions

func NewRandom

func NewRandom(r *rand.Rand) (string, error)

NewRandom creates a new Schedule with a random cron expression

Types

type JobRuntime

type JobRuntime struct {
	// Start is the time the job started
	Start time.Time

	// End is the time the job ended
	End time.Time

	// Error is any error that occurred during the job
	Error error
}

JobRuntime is a record of a job's runtime and any error

type Schedule

type Schedule struct {
	// contains filtered or unexported fields
}

Schedule is a cron schedule created from a cron expression

Usage

To create a new Schedule, use the New function:

  	s, err := crong.New("0 0 * * *", time.UTC)
	if err != nil {
		log.Fatal(err)
	}

To get the next scheduled time after a given time, use the Next method:

next := s.Next(time.Now())

To check if a time matches the schedule, use the Matches method:

if s.Matches(time.Now()) {
	fmt.Println("It's time!")
}

func New

func New(cron string, loc *time.Location) (*Schedule, error)

New creates a new Schedule from a cron expression. loc is the location to use for the schedule (if nil, defaults to time.UTC)

func (*Schedule) Day

func (s *Schedule) Day() string

Day returns the day value of the schedule

func (*Schedule) Hour

func (s *Schedule) Hour() string

Hour returns the hour value of the schedule

func (*Schedule) LogValue

func (s *Schedule) LogValue() slog.Value

func (*Schedule) Matches

func (s *Schedule) Matches(t time.Time) bool

Matches returns true if the schedule matches the given time

func (*Schedule) Minute

func (s *Schedule) Minute() string

Minute returns the minute value of the schedule

func (*Schedule) Month

func (s *Schedule) Month() string

Month returns the month value of the schedule

func (*Schedule) Next

func (s *Schedule) Next(t time.Time) time.Time

Next returns the next scheduled time after the given time

func (*Schedule) Prev

func (s *Schedule) Prev(t time.Time) time.Time

Prev returns the previous scheduled time before the given time

func (*Schedule) String

func (s *Schedule) String() string

String returns the string representation of the schedule

func (*Schedule) UntilNext

func (s *Schedule) UntilNext(t time.Time) time.Duration

UntilNext returns the duration until the next scheduled time after the given time

func (*Schedule) Weekday

func (s *Schedule) Weekday() string

Weekday returns the weekday value of the schedule

type ScheduleState

type ScheduleState int64
const (
	ScheduleStarted ScheduleState = iota + 1
	ScheduleSuspended
	ScheduleStopped
)

type ScheduledJob

type ScheduledJob struct {

	// Failures is the number of times the job has failed
	Failures atomic.Int64

	// ConsecutiveFailures is the number of times the job has failed in a row
	ConsecutiveFailures atomic.Int64

	// Runs is the number of times the job has run
	Runs atomic.Int64

	// Running is the number of times the job is currently running
	Running atomic.Int64
	// contains filtered or unexported fields
}

ScheduledJob is a function that runs on Ticker ticks for a Schedule

func NewScheduledJob

func NewScheduledJob(
	schedule *Schedule,
	opts *ScheduledJobOptions,
	f func(t time.Time) error,
) *ScheduledJob

func ScheduleFunc

func ScheduleFunc(
	ctx context.Context,
	schedule *Schedule,
	opts *ScheduledJobOptions,
	f func(t time.Time) error,
) *ScheduledJob

func (*ScheduledJob) Resume

func (s *ScheduledJob) Resume() bool

Resume resumes job execution after a call to Suspend

func (*ScheduledJob) Runtimes

func (s *ScheduledJob) Runtimes() []*JobRuntime

Runtimes returns a slice of the job's runtimes

func (*ScheduledJob) Start

func (s *ScheduledJob) Start(ctx context.Context) error

func (*ScheduledJob) State

func (s *ScheduledJob) State() ScheduleState

func (*ScheduledJob) Stop

func (s *ScheduledJob) Stop(ctx context.Context) bool

Stop stops job execution. After Stop is called, the job cannot be restarted.

func (*ScheduledJob) Suspend

func (s *ScheduledJob) Suspend() bool

Suspend pauses job execution until Resume is called

type ScheduledJobOptions

type ScheduledJobOptions struct {
	// MaxConcurrent is the maximum number of concurrent job executions.
	// If 0, there is no limit
	MaxConcurrent int

	// TickerReceiveTimeout is the maximum time the job's ticker will
	// wait for the job to receive a tick on the Ticker.C channel
	TickerReceiveTimeout time.Duration

	// MaxFailures is the maximum number of times the job can fail
	// before it is stopped. 0=no limit
	MaxFailures int

	// MaxConsecutiveFailures is the maximum number of consecutive
	// times the job can fail before it is stopped. 0=no limit
	MaxConsecutiveFailures int
}

type Ticker

type Ticker struct {
	C chan time.Time
	// contains filtered or unexported fields
}

Ticker is a cron ticker that sends the current time on the Ticker.C channel when the schedule is triggered

func NewTicker

func NewTicker(
	ctx context.Context,
	schedule *Schedule,
	sendTimeout time.Duration,
) *Ticker

NewTicker creates a new Ticker from a cron expression, sending the current time on Ticker.C when the schedule is triggered. It works similarly to time.Ticker(https://golang.org/pkg/time/#Ticker), but is granular only to the minute. sendTimeout is the maximum time to wait for a receiver to send a tick on the Ticker.C channel (this differs from time.Ticker, allowing some wiggle room for slow receivers). If the provided context is canceled, the ticker will stop automatically.

func (*Ticker) Stop

func (t *Ticker) Stop()

Jump to

Keyboard shortcuts

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