go系列之 cron 表达式
一、简介
robfig/cron 是一个用于 Go 语言的定时任务调度库,它允许开发者以类似于 Unix/Linux 系统中的 cron 守护进程的方式来定义和管理周期性任务。
二、使用教程
c := cron.New()
c.AddFunc("0 30 * * * *", func() { fmt.Println("Every hour on the half hour") })
c.AddFunc("@hourly", func() { fmt.Println("Every hour") })
c.AddFunc("@every 1h30m", func() { fmt.Println("Every hour thirty") })
c.Start()
..
// Funcs are invoked in their own goroutine, asynchronously.
...
// Funcs may also be added to a running Cron
c.AddFunc("@daily", func() { fmt.Println("Every day") })
..
// Inspect the cron job entries' next and previous run times.
inspect(c.Entries())
..
c.Stop() // Stop the scheduler (does not stop any jobs already running).
三、实现原理
3.1 entry 结构体
type Entry struct {ID EntryID// corn configSchedule Schedule// corn next timeNext time.Time// job handlerWrappedJob Job}
3.2 Run 实现原理
// access to the 'running' state variable.
func (c *Cron) run() {c.logger.Info("start")now := c.now()for _, entry := range c.entries {entry.Next = entry.Schedule.Next(now)c.logger.Info("schedule", "now", now, "entry", entry.ID, "next", entry.Next)}for {// Determine the next entry to run.sort.Sort(byTime(c.entries))var timer *time.Timerif len(c.entries) == 0 || c.entries[0].Next.IsZero() {// If there are no entries yet, just sleep - it still handles new entries// and stop requests.timer = time.NewTimer(100000 * time.Hour)} else {// sleep until first entry readytimer = time.NewTimer(c.entries[0].Next.Sub(now))}select {// first entry entercase now = <-timer.C:now = now.In(c.location)c.logger.Info("wake", "now", now)// Run every entry whose next time was less than nowfor _, e := range c.entries {if e.Next.After(now) || e.Next.IsZero() {break}c.startJob(e.WrappedJob)e.Prev = e.Nexte.Next = e.Schedule.Next(now)c.logger.Info("run", "now", now, "entry", e.ID, "next", e.Next)}// new add entry case newEntry := <-c.add:timer.Stop()now = c.now()newEntry.Next = newEntry.Schedule.Next(now)c.entries = append(c.entries, newEntry)c.logger.Info("added", "now", now, "entry", newEntry.ID, "next", newEntry.Next)break}}