https://github.com/tomasbasham/escalsched
https://github.com/tomasbasham/escalsched
Last synced: 3 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/tomasbasham/escalsched
- Owner: tomasbasham
- License: mit
- Created: 2026-01-30T22:26:39.000Z (5 months ago)
- Default Branch: master
- Last Pushed: 2026-02-02T01:28:16.000Z (5 months ago)
- Last Synced: 2026-02-02T08:58:28.650Z (5 months ago)
- Language: Go
- Homepage:
- Size: 23.4 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
# escalsched [](https://github.com/tomasbasham/escalsched/actions/workflows/test.yaml)
A Go scheduler that implements priority-based task scheduling with time-based
escalation policies. Tasks are processed according to their priority levels,
whilst escalation policies ensure that lower-priority tasks don't experience
indefinite starvation by automatically promoting them when processing delays
exceed configured thresholds.
The scheduler provides fairness guarantees through an optional fairness window,
which temporarily suspends priority-based ordering to process tasks in FIFO
order when the scheduler has been idle, preventing permanent starvation of
lower-priority work.
## Prerequisites
You will need the following things properly installed on your computer:
- [Go](https://golang.org/): any one of the **three latest major**
[releases](https://golang.org/doc/devel/release.html)
## Installation
With [Go module](https://go.dev/wiki/Modules) support (Go 1.11+), simply add the
following import
```go
import "github.com/tomasbasham/escalsched"
```
to your code, and then `go [build|run|test]` will automatically fetch the
necessary dependencies.
Otherwise, to install the `escalsched` module, run the following command:
```bash
go get -u github.com/tomasbasham/escalsched
```
## Usage
To use this module, create a scheduler instance and schedule tasks with
priorities. The scheduler processes tasks in priority order, with
higher-priority tasks being unscheduled before lower-priority ones.
### Basic Scheduling
```go
// Create a new scheduler for string tasks.
scheduler := escalsched.New[string]()
// Schedule tasks with different priorities.
scheduler.Schedule("low-priority-task", escalsched.Priorities.Low)
scheduler.Schedule("high-priority-task", escalsched.Priorities.High)
scheduler.Schedule("normal-priority-task", escalsched.Priorities.Normal)
// Retrieve the next task (blocks until available).
ctx := context.Background()
task := scheduler.Next(ctx)
fmt.Println(task.Value) // Outputs: "high-priority-task"
```
### Escalation Policies
Define escalation policies to automatically increase task priority after
specified durations:
```go
scheduler := escalsched.New[string]()
// Define an escalation policy.
policy := escalsched.EscalationPolicy{
{After: 100 * time.Millisecond, Target: escalsched.Priorities.High},
}
// Schedule a task with the policy.
task := scheduler.ScheduleWithPolicy("important-task", escalsched.Priorities.Low, policy)
// After 100ms, the task will automatically escalate to High priority if it has
// not yet been processed.
```
### Manual Escalation
Tasks can be manually escalated at any time:
```go
scheduler := escalsched.New[string]()
task := scheduler.Schedule("task", escalsched.Priorities.Low)
// Manually escalate to high priority.
scheduler.Escalate(task, escalsched.Priorities.High)
```
### Fairness Window
Configure a fairness window to prevent starvation by temporarily processing
tasks in FIFO order:
```go
scheduler := escalsched.New[string](
escalsched.WithFairnessWindow(5 * time.Second),
)
// If the scheduler is idle for 5 seconds, the next task will be unscheduled
// in FIFO order regardless of priority.
```
### Metrics Hooks
Monitor scheduler events by implementing the `MetricsHook` interface:
```go
type MyMetrics struct{}
func (m *MyMetrics) OnSchedule(task *escalsched.Task[string]) {
fmt.Printf("Scheduled: %s\n", task.Value)
}
func (m *MyMetrics) OnUnschedule(task *escalsched.Task[string]) {
fmt.Printf("Unscheduled: %s\n", task.Value)
}
func (m *MyMetrics) OnEscalate(task *escalsched.Task[string], from, to escalsched.Priority) {
fmt.Printf("Escalated %s from %s to %s\n", task.Value, from, to)
}
scheduler := escalsched.New[string](
escalsched.WithMetricsHook(&MyMetrics{}),
)
```
### Concurrent Workers
The scheduler is thread-safe and supports multiple concurrent workers:
```go
scheduler := escalsched.New[int]()
// Schedule tasks.
for i := range 100 {
scheduler.Schedule(i, escalsched.Priorities.Normal)
}
numWorkers := 4
ctx := context.Background()
// Use WaitGroup to know when all workers are done.
var wg sync.WaitGroup
wg.Add(numWorkers)
worker := func(id int) {
defer wg.Done()
for task := range scheduler.Tasks(ctx)
fmt.Printf("Worker %d: Processing %d\n", w, task.Value)
}
}
// Start workers.
for i := range numWorkers {
go worker(i + 1)
}
wg.Wait()
```
### Unscheduling Tasks
Remove tasks from the scheduler without processing them:
```go
scheduler := escalsched.New[string]()
task := scheduler.Schedule("task", escalsched.Priorities.Normal)
// Remove the task from the scheduler.
scheduler.UnscheduleTask(task)
```
## License
This project is licensed under the [MIT License](LICENSE).