Task scheduler implementations in Go, from synchronous to heap-based.
This repository contains the source code for Evolution of a Task Scheduler in Go, which explores the tradeoffs between timing, concurrency, and efficiency as the design evolves from dynamic sleep through polling and worker pools to a final heap-based design.
go get github.com/hackebrot/go-task-schedulerAll schedulers implement a common interface:
// Scheduler manages and executes tasks at their scheduled times.
type Scheduler interface {
// Schedule adds a task to the scheduler.
Schedule(task Task)
// Start begins the scheduler's background processing.
// It runs until the provided context is cancelled.
Start(ctx context.Context)
// PendingTasksCount returns the number of tasks waiting to be executed.
PendingTasksCount() int
}
// Task represents a schedulable unit of work with an execution time.
type Task interface {
// Execute runs the task and returns an error if the execution fails.
Execute() error
// ExecuteAt returns the time when this task should be executed.
ExecuteAt() time.Time
// ID returns a unique identifier for this task (used for logging).
ID() string
}| Scheduler | Execution Model | Time Complexity | Space Complexity | Best For | Source |
|---|---|---|---|---|---|
| Dynamic Sleep | Sequential | O(n) per batch |
O(n) |
Low concurrency requirements | cmd/dynamicsleep |
| Polling | Concurrent (unbounded) | O(n) per interval |
O(n) |
Low task counts, minimal code complexity | cmd/polling |
| Worker Pool | Concurrent (bounded) | O(n) per interval |
O(n) |
Controlled concurrency, result tracking | cmd/workerpool |
| Heap | Concurrent (bounded) | O(log n) per dispatch |
O(n) |
High task volumes, production systems* | cmd/heap |
*Production use requires additional work: persistence, retries, observability, graceful shutdown, and more.
MIT