framework1/framework/cobra/hade_command_distributed.go

74 lines
1.9 KiB
Go
Raw Normal View History

2024-10-20 22:56:46 +08:00
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-cronServiceName需要填写
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)
}
})
}