In-memory sorted set with TTL-based leasing for Go worker pools and task queues.
Keys are ordered by uint64 score. Multiple workers can safely lease, release, renew, or remove keys concurrently.
go get github.com/ariadata/leased-sorted-set@v1.0.0package main
import (
"time"
leased_sorted_set "github.com/ariadata/leased-sorted-set"
)
func main() {
s := leased_sorted_set.New()
s.Add("task-a", 10)
s.Add("task-b", 20)
key, score, ok := s.Lease(30 * time.Second)
if !ok {
return
}
// process key/score ...
_ = score
// success
s.Remove(key)
// or retry later
// s.Release(key)
}| Method | Description |
|---|---|
Add(key, score) |
Insert if absent (ignore duplicates) |
Lease(ttl) |
Lock lowest-scored available key |
LeaseMax(ttl) |
Lock highest-scored available key |
LeaseKey(key, ttl) |
Lock a specific key |
Release(key) |
Unlock for retry |
Renew(key, ttl) |
Extend active lease |
Remove(key) |
Delete permanently |
Available() |
Count of unleased keys |
PruneAndKeepLast(n) |
Drop lowest scores, keep top n |
See pkg.go.dev for full docs.
Typical flow for background processors:
Producer → Add(key, score)
Worker → Lease(ttl) or LeaseMax(ttl)
→ process
→ Remove(key) on success
→ Release(key) on retryable error
Scale workers using Available() as backlog signal.
If you previously vendored this under internal/leased_sorted_set (e.g. in sample-app):
Before
import "sample-app/internal/leased_sorted_set"
pool := worker.New(cfg, leased_sorted_set.New(), processor)After
import leased_sorted_set "github.com/ariadata/leased-sorted-set"
pool := worker.New(cfg, leased_sorted_set.New(), processor)Update types in constructors from *leased_sorted_set.Set to *leased_sorted_set.Set, then remove the local internal/leased_sorted_set folder.
go get github.com/ariadata/leased-sorted-set@v1.0.0- In
main.goandinternal/worker/pool.go, swap the import - Delete
internal/leased_sorted_set/
No method signatures change — only the import path and package name.
MIT