74 lines
1.9 KiB
Go
74 lines
1.9 KiB
Go
package cobra
|
||
|
||
import (
|
||
"github.com/Superdanda/hade/framework/contract"
|
||
"github.com/robfig/cron/v3"
|
||
"log"
|
||
"time"
|
||
)
|
||
|
||
// AddDistributedCronCommand 实现一个分布式定时器
|
||
// serviceName 这个服务的唯一名字,不允许带有空格
|
||
// spec 具体的执行时间
|
||
// cmd 具体的执行命令
|
||
// holdTime 表示如果我选择上了,这次选择持续的时间,也就是锁释放的时间
|
||
func (c *Command) AddDistributedCronCommand(serviceName string,
|
||
spec string,
|
||
cmd *Command,
|
||
holdTime time.Duration) {
|
||
|
||
root := c.Root()
|
||
|
||
// 初始化cron
|
||
if root.Cron == nil {
|
||
root.Cron = cron.New(cron.WithParser(cron.NewParser(cron.SecondOptional | cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow | cron.Descriptor)))
|
||
root.CronSpecs = []CronSpec{}
|
||
}
|
||
|
||
// cron命令的注释,这里注意Type为distributed-cron,ServiceName需要填写
|
||
root.CronSpecs = append(root.CronSpecs, CronSpec{
|
||
Type: "distributed-cron",
|
||
Cmd: cmd,
|
||
Spec: spec,
|
||
ServiceName: serviceName,
|
||
})
|
||
|
||
appService := root.MustMakeApp()
|
||
distributeService := root.GetContainer().MustMake(contract.DistributedKey).(contract.Distributed)
|
||
appID := appService.AppId()
|
||
|
||
// 复制要执行的command为cronCmd,并且设置为rootCmd
|
||
var cronCmd Command
|
||
ctx := root.Context()
|
||
cronCmd = *cmd
|
||
cronCmd.args = []string{}
|
||
cronCmd.SetParentNull()
|
||
|
||
// cron增加匿名函数
|
||
root.Cron.AddFunc(spec, func() {
|
||
// 防止panic
|
||
defer func() {
|
||
if err := recover(); err != nil {
|
||
log.Println(err)
|
||
}
|
||
}()
|
||
|
||
// 节点进行选举,返回选举结果
|
||
selectedAppID, err := distributeService.Select(serviceName, appID, holdTime)
|
||
if err != nil {
|
||
return
|
||
}
|
||
|
||
// 如果自己没有被选择到,直接返回
|
||
if selectedAppID != appID {
|
||
return
|
||
}
|
||
|
||
// 如果自己被选择到了,执行这个定时任务
|
||
err = cronCmd.ExecuteContext(ctx)
|
||
if err != nil {
|
||
log.Println(err)
|
||
}
|
||
})
|
||
}
|