goschd

package module
v1.0.1 Latest Latest
Warning

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

Go to latest
Published: Oct 20, 2025 License: GPL-3.0 Imports: 5 Imported by: 0

README

Go Scheduler Package

goschd

Go Reference Lint Build Go Version Go Report Card License

The Go Scheduler package provides a flexible and lightweight task scheduling mechanism for Go applications. You can schedule tasks to run periodically using either duration strings or cron expressions. It supports delayed starts, one-time execution, single-instance execution, and custom error handling.

Features

  • Flexible Scheduling:
    Schedule tasks using either standard Go duration strings (e.g., "1s", "500ms") or cron expressions (e.g., "* * * * * *").

  • Immediate or Delayed Start:
    Configure tasks to start immediately (FirstRun) or at a later time using StartAfter.

  • One-Time or Recurring Tasks:
    Use RunOnce to run a task only once or leave it running repeatedly.

  • Single Instance Execution:
    Prevent concurrent execution of tasks with the RunSingleInstance flag.

  • Error Handling:
    Supply custom error handlers (ErrFunc or ErrFuncWithTaskContext) to process errors from task execution.

  • Thread-Safe:
    Built-in synchronization ensures safe concurrent access and modifications.

Installation

Install the package using go get. Replace github.com/raykavin/goschd with your actual module path.

go get github.com/raykavin/goschd

Usage

Import the package into your project:

import "github.com/raykavin/goschd"

Scheduling a Simple Task

The following example demonstrates scheduling a task that prints a message every second.

package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/raykavin/goschd"
)

func main() {
	scheduler := goschd.NewTaskScheduler()

	task := &goschd.Task{
		Interval: "1s",     // Execute every 1 second
		RunOnce:  false,    // Recurring task
		FirstRun: true,     // Execute immediately upon scheduling
		TaskFunc: func(ctx context.Context) error {
			fmt.Println("Simple task executed!")
			return nil
		},
	}

	if err := scheduler.Add("simpleTask", task); err != nil {
		log.Fatalf("Error adding task: %v", err)
	}

	// Keep the application running
	select {}
}

Scheduling a Cron Task

Schedule a task using a cron expression (with seconds) to fire every 5 seconds.

package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/raykavin/goschd"
)

func main() {
	scheduler := goschd.NewTaskScheduler()

	cronTask := &goschd.Task{
		Interval: "* * * * * *", // Cron expression: every second
		RunOnce:  false,         // Recurring task
		FirstRun: true,          // Execute immediately upon scheduling
		TaskFunc: func(ctx context.Context) error {
			fmt.Println("Cron task executed!")
			return nil
		},
	}

	if err := scheduler.Add("cronTask", cronTask); err != nil {
		log.Fatalf("Error adding cron task: %v", err)
	}

	select {}
}

Delayed Start Task

Schedule a task to start after a specific delay using StartAfter.

package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/raykavin/goschd"
)

func main() {
	scheduler := goschd.NewTaskScheduler()

	delayedTask := &goschd.Task{
		Interval:   "2s",                           // Task repeats every 2 seconds
		RunOnce:    false,                          // Recurring task
		FirstRun:   false,                          // Do not run immediately
		StartAfter: time.Now().Add(5 * time.Second),  // Delay start by 5 seconds
		TaskFunc: func(ctx context.Context) error {
			fmt.Println("Delayed task executed!")
			return nil
		},
	}

	if err := scheduler.Add("delayedTask", delayedTask); err != nil {
		log.Fatalf("Error adding delayed task: %v", err)
	}

	select {}
}

Error Handling

Handle errors produced by a task using a custom error callback.

package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/raykavin/goschd"
)

func main() {
	scheduler := schdulerext.NewTaskScheduler()

	errorTask := &goschd.Task{
		Interval: "1s",    // Execute every 1 second
		RunOnce:  true,    // Run only once
		FirstRun: true,    // Execute immediately
		TaskFunc: func(ctx context.Context) error {
			return fmt.Errorf("simulated error")
		},
		ErrFunc: func(err error) {
			fmt.Printf("Error handler invoked: %v\n", err)
		},
	}

	if err := scheduler.Add("errorTask", errorTask); err != nil {
		log.Fatalf("Error adding error task: %v", err)
	}

	time.Sleep(1500 * time.Millisecond)
}

Testing

The package includes a suite of tests covering task scheduling, error handling, cloning, and more. To run the tests, use:

go test -v

🤝 Contributing

Contributions to GoSchd are welcome! Here are some ways you can help improve the project:

  • Report bugs and suggest features by opening issues on GitHub
  • Submit pull requests with bug fixes or new features
  • Improve documentation to help other users and developers
  • Share your custom strategies with the community

📄 License

GoSchd is distributed under the GNU General Public License v3.0.
For complete license terms and conditions, see the LICENSE file in the repository.

Copyright © Raykavin Meireles


📬 Contact

For support, collaboration, or questions about GoSchd:

Email: raykavin.meireles@gmail.com
GitHub: @raykavin
LinkedIn: @raykavin.dev
Instagram: @raykavin.dev

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrTaskIDInUse is returned when attempting to add a task with an ID that already exists.
	ErrTaskIDInUse = errors.New("task id already in use")

	// ErrTaskFuncNil is returned when a task is created without a function to execute.
	ErrTaskFuncNil = errors.New("task function cannot be nil")

	// ErrTaskInterval is returned when a task is created without a valid interval.
	ErrTaskInterval = errors.New("task interval must be defined")

	// ErrInvalidTaskInterval is returned when a task is created with an invalid interval format.
	ErrInvalidTaskInterval = errors.New("invalid task interval format")

	// ErrTaskNotFound is returned when attempting to lookup a task that doesn't exist.
	ErrTaskNotFound = errors.New("could not find task within the task list")
)

Functions

This section is empty.

Types

type Logger

type Logger interface {
	WithField(key string, value any) Logger
	WithError(err error) Logger

	// Standard log functions
	Debug(args ...any)
	Info(args ...any)
}

Defines the logger interface

type Scheduler

type Scheduler struct {
	sync.RWMutex // RWMutex for managing concurrent access to tasks.
	// contains filtered or unexported fields
}

Scheduler manages a collection of scheduled tasks. It provides thread-safe operations for adding, removing, and looking up tasks by their unique identifiers.

func NewTaskScheduler

func NewTaskScheduler(opts ...SchedulerOpts) *Scheduler

NewTaskScheduler creates and returns a new instance of the task scheduler. The scheduler is ready to use immediately after creation.

func (*Scheduler) Add

func (s *Scheduler) Add(id string, task *Task) error

Add registers a new task with the scheduler using the provided ID. The task will be validated and scheduled according to its configuration. Returns an error if the ID is already in use or if the task configuration is invalid.

Example:

task := &Task{
    Interval: "5s",
    TaskFunc: func(ctx context.Context) error {
        fmt.Println("Task executed")
        return nil
    },
}
err := scheduler.Add("my-task", task)

func (*Scheduler) Del

func (s *Scheduler) Del(name string)

Del removes a task from the scheduler by its ID. The task's context will be cancelled and its timer will be stopped. If the task doesn't exist, this operation is a no-op.

func (*Scheduler) Lookup

func (s *Scheduler) Lookup(name string) (*Task, error)

Lookup retrieves a task by its ID. Returns a clone of the task to prevent external modifications to the original task state. Returns ErrTaskNotFound if the task doesn't exist.

func (*Scheduler) Tasks

func (s *Scheduler) Tasks() map[string]*Task

Tasks returns a map of all scheduled tasks, keyed by their IDs. The returned tasks are clones to prevent external modifications. This method is useful for inspecting the current state of all scheduled tasks.

type SchedulerOpts

type SchedulerOpts func(*Scheduler)

SchedulerOptions defines configuration options for the Scheduler.

func WithLogger

func WithLogger(logger Logger) SchedulerOpts

WithLogger sets a custom logger for the Scheduler.

type Task

type Task struct {
	sync.RWMutex // Managing concurrent modifications to task properties.

	// TaskContext provides contextual information and ID for the task.
	TaskContext TaskContext

	// Interval specifies when the task should run. Can be a duration string (e.g., "5s", "1m")
	// or a cron expression (e.g., "0 0 * * *" for daily at midnight).
	Interval string

	// RunOnce indicates if the task should run only once and then be removed from the scheduler.
	RunOnce bool

	// FirstRun indicates if the task should run immediately upon being scheduled.
	FirstRun bool

	// RunSingleInstance prevents concurrent instances of the task from running.
	// If true, a new execution will be skipped if the previous one is still running.
	RunSingleInstance bool

	// StartAfter specifies the earliest time when the task should start executing.
	// The task will not run before this time.
	StartAfter time.Time

	// TaskFunc is the main function to execute. It receives a context for cancellation.
	// Either TaskFunc or FuncWithTaskContext must be provided.
	TaskFunc func(ctx context.Context) error

	// ErrFunc is called when TaskFunc returns an error.
	ErrFunc func(error)

	// FuncWithTaskContext is an alternative to TaskFunc that receives TaskContext instead of context.Context.
	// Either TaskFunc or FuncWithTaskContext must be provided.
	FuncWithTaskContext func(TaskContext) error

	// ErrFuncWithTaskContext is called when FuncWithTaskContext returns an error.
	ErrFuncWithTaskContext func(TaskContext, error)
	// contains filtered or unexported fields
}

Task represents a scheduled task with its configuration and execution parameters. It supports various execution modes including one-time runs, recurring intervals, and cron-based scheduling.

func (*Task) Clone

func (t *Task) Clone() *Task

Clone creates a deep copy of the task. This is useful for creating task templates or when you need to inspect a task's configuration without affecting the original. The clone shares the same context and timer references as the original.

type TaskContext

type TaskContext struct {
	Context context.Context // Context for managing the task's lifecycle.
	// contains filtered or unexported fields
}

TaskContext provides contextual information for task execution, including the task's unique identifier and execution context.

func (TaskContext) ID

func (ctx TaskContext) ID() string

ID returns the unique identifier of the task.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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