Languages: English | 中文
xcron is a high-performance Go cron scheduling library built on the ants goroutine pool. It supports flexible job configuration and efficient task execution.
Architecture: Cron → Engine (goroutine pool + rate limiting) → Scheduler (timing + Pick + JobWrapper)
- Standard cron expressions
- Fixed-interval scheduling (
Every/Schedule) - High-performance execution via ants goroutine pool
- Custom time zones
- Job cancellation and cleanup (
Remove) - Custom job wrappers (
JobWrapper) - Custom schedule parsers (
WithParser) - Custom
Engine/Schedulerfor extended execution strategies - Execution rate limiting (
WithRate) and goroutine pool sizing (WithMaxWorkers) - Graceful shutdown
- Extensible capabilities such as timeout control via
JobWrapper
go get github.com/danielhookx/xcronpackage main
import (
"github.com/danielhookx/xcron"
)
func main() {
c := xcron.NewCron()
// Run every 5 minutes
c.AddFunc("*/5 * * * *", func() {
println("running scheduled job")
})
c.Start()
// In production, prefer the graceful shutdown pattern in the section below
// and wait for <-ctx.Done() so in-flight jobs can finish
defer c.Stop()
select {}
}package main
import (
"github.com/danielhookx/xcron"
"time"
)
func main() {
c := xcron.NewCron(
xcron.WithLocation(time.UTC),
)
c.AddFunc("0 0 * * *", func() {
println("runs daily at midnight UTC")
})
c.Start()
defer c.Stop()
select {}
}In addition to cron expressions, use Schedule + Every for fixed intervals:
package main
import (
"github.com/danielhookx/xcron"
"time"
)
func main() {
c := xcron.NewCron()
c.Schedule(xcron.Every(30*time.Second), xcron.FuncJob(func() {
println("runs every 30 seconds")
}))
c.Start()
defer c.Stop()
select {}
}package main
import (
"github.com/danielhookx/xcron"
)
func main() {
c := xcron.NewCron()
id, _ := c.AddFunc("*/10 * * * *", func() {
println("runs every 10 minutes")
}, xcron.WithID("custom-task-1"))
entry := c.Entry(id)
if entry != nil {
println("job exists")
}
// Remove the job; triggers CancelHandler to clean up scheduling
c.Remove(id)
c.Start()
defer c.Stop()
select {}
}By default, NewCron() is equivalent to NewEngine(NewJobScheduler(loc)). To customize pool size or execution rate, assemble components manually:
package main
import (
"github.com/danielhookx/xcron"
"time"
)
func main() {
scheduler := xcron.NewJobScheduler(
time.Local,
xcron.WithPickTimeout(10*time.Millisecond),
)
engine := xcron.NewEngine(
scheduler,
xcron.WithMaxWorkers(100), // pool size; 0 uses ants default
xcron.WithRate(50), // max 50 triggers per second; <=0 is full speed
)
c := xcron.NewCron(xcron.WithEngine(engine))
c.AddFunc("*/5 * * * *", func() {
println("running scheduled job")
})
c.Start()
defer c.Stop()
select {}
}JobWrapper can add timeout control, retries, and other extensions:
package main
import (
"context"
"github.com/danielhookx/xcron"
"time"
)
func timeoutJobWrapper(schedule xcron.Schedule, job xcron.Job) (xcron.Job, xcron.CancelHandler) {
return xcron.FuncJob(func() {
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
done := make(chan struct{})
go func() {
job.Run()
close(done)
}()
select {
case <-ctx.Done():
println("job timed out")
case <-done:
println("job completed")
}
}), nil
}
func main() {
c := xcron.NewCron()
c.AddFunc("*/5 * * * *", func() {
time.Sleep(40 * time.Second)
println("job completed")
}, xcron.WithJobWrapper(timeoutJobWrapper))
c.Start()
defer c.Stop()
select {}
}xcron supports graceful shutdown so in-flight jobs can finish:
package main
import (
"github.com/danielhookx/xcron"
"os"
"os/signal"
"syscall"
)
func main() {
c := xcron.NewCron()
c.AddFunc("*/5 * * * *", func() {
println("running scheduled job")
})
c.Start()
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
<-sigChan
ctx, _ := c.Stop()
<-ctx.Done()
println("all jobs stopped")
}WithLocation(loc *time.Location)— set time zoneWithParser(parser ScheduleParser)— set cron expression parserWithEngine(engine Engine)— inject a custom Engine
WithMaxWorkers(n int)— ants pool size; 0 uses defaultWithRate(n int)— max triggers per second; <=0 is full speed
WithPickTimeout(d time.Duration)— Pick wait timeout; default 5ms
WithID(id EntryID)— set job IDWithJobWrapper(wrapper JobWrapper)— set job wrapper
- Call
Stop()before exit to release resources; in production, wait for the context returned byStop()so running jobs can finish - Use
JobWrapperto implement timeout control and other extensions - Set goroutine pool size (
WithMaxWorkers) appropriately to avoid wasting resources - Handle errors during job execution
MIT License