当前位置: 首页 > news >正文

golang封装可扩展的crontab

1. 导入cron第三方包

go get github.com/robfig/cron/v3

2. 申明变量

// 单个cron的interface
type RunCronItem interface {Run()         // 计划任务执行体Start() error // 初始化用的,第一次启动的时候,调用,后续不再执行Name() string // 计划任务配置名
}// 申明所有计划任务的配置
type CronTaskItem struct {name    stringrunItem RunCronItem
}// JobStatus 任务状态
type JobStatus struct {LastRun     time.TimeLastSuccess boolIsRunning   boolMutex       sync.Mutex
}// CronManager Cron任务管理器
type CronManager struct {cron      *cron.Cronjobs      map[string]func()jobStatus map[string]*JobStatusconfig    config.ProxyConfig // 此处为配置文件
}

3. 配置文件

config.yaml

cron_jobs:start_file_resend:Schedule: "0 */2 * * * *"  # 每2分钟将trace文件发送到客户端Enabled: falseDescription: "每2分钟将文件发到云端"

config.go

import ("flag""github.com/spf13/viper""log"
)type ProxyConfig struct {
...LogLevel     uint32                   `mapstructure:"log_level"`Log          LogConfig                `mapstructure:"log"`CronJobs     map[string]CronJobConfig `mapstructure:"cron_jobs"` //此处为计划任务的配置
....}

4. 创建计划任务管理器


// NewCronManager 创建Cron管理器
func NewCronManager(appConfig config.ProxyConfig) *CronManager {// 创建Cron实例,使用秒级精度(支持6位cron表达式)c := cron.New(cron.WithSeconds())manager := &CronManager{cron:      c,jobs:      make(map[string]func()),jobStatus: make(map[string]*JobStatus),config:    appConfig,}return manager
}// AddJob 添加任务
func (m *CronManager) AddJob(name string, jobItem RunCronItem) error {// 查找配置jobConfig, exists := m.config.CronJobs[name]if !exists {return fmt.Errorf("定时任务名称找不到:%s", name)}if !jobConfig.Enabled {logger.Log.Error("定时任务未启用", zap.String("name", name))return nil}// 初始化任务状态m.jobStatus[name] = &JobStatus{}// 包装任务函数,添加并发控制wrappedFunc := func() {status := m.jobStatus[name]// 检查任务是否正在运行status.Mutex.Lock()if status.IsRunning {logger.Log.Info("定时任务已经运行中,请稍后", zap.String("name", name))status.Mutex.Unlock()return}// 标记任务开始运行status.IsRunning = truestatus.LastRun = time.Now()status.Mutex.Unlock()// 执行任务logger.Log.Debug("定时任务正在执行", zap.String("name", name))startTime := time.Now()defer func() {// 捕获panic,确保任务状态正确更新if r := recover(); r != nil {logger.Log.Error(fmt.Sprintf("定时任务 %s panicked: %v", name, r))status.LastSuccess = false}// 更新任务状态status.Mutex.Lock()status.IsRunning = falsestatus.Mutex.Unlock()duration := time.Since(startTime)logger.Log.Debug(fmt.Sprintf("定时任务完成:%s, duration: %v", name, duration))}()// 执行实际任务jobItem.Run()status.LastSuccess = true}// 添加任务到cronm.jobs[name] = wrappedFunc_, err := m.cron.AddFunc(jobConfig.Schedule, wrappedFunc)if err != nil {return fmt.Errorf("failed to add job %s: %v", name, err)}logger.Log.Debug(fmt.Sprintf("添加定时任务成功: %s with schedule: %s", name, jobConfig.Schedule))return nil
}// StartAllJobs 启动所有配置中启用的任务
func (m *CronManager) StartAllJobs() error {for name := range m.config.CronJobs {// 这里不直接添加任务,因为任务函数需要外部提供// 外部需要先调用 AddJob 添加具体的任务函数logger.Log.Debug(fmt.Sprintf("启用所有配置中的定时任务: %s", name))}m.cron.Start()logger.Log.Debug("定时任务已全部开启")return nil
}// Start 启动所有任务
func (m *CronManager) Start() {m.cron.Start()logger.Log.Debug("Cron manager started")
}// Stop 停止所有任务
func (m *CronManager) Stop() {m.cron.Stop()logger.Log.Debug("Cron manager stopped")
}// GetJobStatus 获取任务状态
func (m *CronManager) GetJobStatus(name string) (*JobStatus, error) {status, exists := m.jobStatus[name]if !exists {return nil, fmt.Errorf("job %s not found", name)}return status, nil
}// ListJobs 列出所有任务
func (m *CronManager) ListJobs() []string {var jobs []stringfor name := range m.jobs {jobs = append(jobs, name)}return jobs
}

5. 配置cron和启动


// 此处配置您的计划任务列表
func crontMangerList() []CronTaskItem {cronTaskList := []RunCronItem{... // 这里可以配置你自己的计划任务的struct,返回满足interface RunCronItem}crontaskItems := make([]CronTaskItem, 0, len(cronTaskList))for _, item := range cronTaskList {crontaskItems = append(crontaskItems, CronTaskItem{name:    item.Name(),runItem: item,})}return crontaskItems
}// 启动job客户端
func InitCronJobClient(config config.ProxyConfig) {manager := NewCronManager(config)// 添加任务,使用 WaitGroup 跟踪cronList := crontMangerList()for _, cronItem := range cronList {err := manager.AddJob(cronItem.name, cronItem.runItem)if err != nil {logger.Log.Error("加入定时任务失败job:%s err:%v", zap.String("job_name", cronItem.name), zap.Error(err))}err = cronItem.runItem.Start()if err != nil {panic(fmt.Sprintf("计划任务初始化失败:%v", err))}}// 启动 Cron 管理器manager.Start()logger.Log.Info("CronJob InitCronJobClient")
}

http://www.dtcms.com/a/554113.html

相关文章:

  • 南京美容网站建设饿了吗网站建设思路
  • 投诉网站怎么做做短视频的能跟几个网站签约
  • 网站维护怎么收费腾讯企点官网入口
  • 高频 Redis 面试题答案解析
  • wordpress 导航站主题系统自动删除了wordpress
  • LeetCode 面试经典 150_链表_分隔链表(65_86_C++_中等)(拆分+尾插法)
  • 一种MP3文件的压缩方法
  • 做网站时候图片和视频放在哪里c 2015 做网站
  • puppeteer函数笔记,设置token跳过登录、自动选择图片上传等
  • 雄安网站建设400多少钱郑州关键词网站优化排名
  • 在使用openfe出现NameError: name ‘exit‘ is not defined的解决方案
  • 【计算机通识】认识 RESTful API
  • 使用cJosn将数据读写文件
  • 做软件搜狗seo软件
  • 仿土巴兔网站建设学院网站建设流程
  • DeerFlow多智能体项目分析-向量数据库实现知识检索的源码解析
  • 001前端查询组件
  • AI在线客服搭建实战指南:三步构建7×24小时智能服务系统
  • TSMaster常用函数
  • 伯位数智模式为商家经营带来的变革与机遇
  • 网盘怎么做电影网站网站在公司做有什么要求吗
  • 介绍一下 multiprocessing 的 Manager模块
  • 网页建站总结报告网站建设初期怎么添加内容
  • C语言——猜数字游戏(rand、srand、time函数学习)
  • 多媒体网站开发实战装修设计软件免费
  • Rust流程控制(下):loop、while、for循环
  • 使用 UV 工具管理 Python 项目的常用命令
  • 解析视频汇聚平台EasyCVR强大的设备统一管理能力,助力构筑安防融合感知的基石
  • 南通做网站的手机怎么看网页源代码
  • 温州网上推广什么网站好深圳网络推广团队