diff --git a/g/os/gcron/gcron.go b/g/os/gcron/gcron.go index d626bd79e..df57f653a 100644 --- a/g/os/gcron/gcron.go +++ b/g/os/gcron/gcron.go @@ -8,6 +8,8 @@ package gcron import ( + "errors" + "fmt" "gitee.com/johng/gf/g/container/garray" "gitee.com/johng/gf/g/container/gtype" "gitee.com/johng/gf/g/os/gtime" @@ -21,32 +23,84 @@ type Entry struct { Spec string // 注册定时任务时间格式 Cmd string // 注册定时任务名称 Time *gtime.Time // 注册时间 + Name string // 定时任务名称 + cron *cron.Cron // 底层定时管理对象 } var ( // 默认的cron管理对象 defaultCron = cron.New() - // 当前cron的运行状态(0: 未执行; >0: 运行中) + // 当前cron的运行状态(0: 未执行; > 0: 运行中) cronStatus = gtype.NewInt() // 注册定时任务项 cronEntries = garray.New(0, 0, true) ) -// 添加执行方法 -func Add(spec string, f func()) error { - // 底层的AddFunc是并发安全的 - err := defaultCron.AddFunc(spec, f) - if err == nil { - if cronStatus.Add(1) == 1 { - go defaultCron.Run() +// 添加执行方法,可以给定名字,以便于后续执行删除 +func Add(spec string, f func(), name ... string) error { + if len(name) > 0 { + if Search(name[0]) != nil { + return errors.New(fmt.Sprintf(`cron job "%s" already exists`, name[0])) + } + c := cron.New() + if err := c.AddFunc(spec, f); err == nil { + cronEntries.Append(Entry{ + Spec : spec, + Cmd : runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name(), + Time : gtime.Now(), + Name : name[0], + cron : c, + }) + go c.Run() + } else { + return err + } + } else { + if err := defaultCron.AddFunc(spec, f); err == nil { + if cronStatus.Add(1) == 1 { + go defaultCron.Run() + } + cronEntries.Append(Entry{ + Spec : spec, + Cmd : runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name(), + Time : gtime.Now(), + }) + } else { + return err } - cronEntries.Append(Entry{ - Spec : spec, - Cmd : runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name(), - Time : gtime.Now(), - }) } - return err + return nil +} + +// 检索指定名称的定时任务 +func Search(name string) *Entry { + entry, _ := searchEntry(name) + return entry +} + +// 检索指定名称的定时任务 +func searchEntry(name string) (*Entry, int) { + entry := (*Entry)(nil) + index := -1 + cronEntries.RLockFunc(func(array []interface{}) { + for k, v := range array { + e := v.(Entry) + if e.Name == name { + entry = &e + index = k + break + } + } + }) + return entry, index +} + +// 根据指定名称删除定时任务 +func Remove(name string) { + if entry, index := searchEntry(name); index >= 0 { + entry.cron.Stop() + cronEntries.Remove(index) + } } // 获取所有已注册的定时任务项 diff --git a/geg/os/gcron/gcron.go b/geg/os/gcron/gcron.go index 595b89f05..5f2ab5c42 100644 --- a/geg/os/gcron/gcron.go +++ b/geg/os/gcron/gcron.go @@ -9,9 +9,14 @@ import ( func main() { gcron.Add("0 30 * * * *", func() { fmt.Println("Every hour on the half hour") }) - gcron.Add("* * * * * *", func() { fmt.Println("Every second") }) + gcron.Add("* * * * * *", func() { fmt.Println("Every second") }, "second-cron") gcron.Add("@hourly", func() { fmt.Println("Every hour") }) gcron.Add("@every 1h30m", func() { fmt.Println("Every hour thirty") }) g.Dump(gcron.Entries()) + + time.Sleep(3*time.Second) + + gcron.Remove("second-cron") + time.Sleep(3*time.Second) } \ No newline at end of file