Skip to content

任务调度

youlai-gin 支持定时任务调度,实现异步任务和定时处理。

定时任务

1. 基于 Cron

go
import "github.com/robfig/cron/v3"

// pkg/scheduler/scheduler.go
type Scheduler struct {
    cron *cron.Cron
}

func NewScheduler() *Scheduler {
    return &Scheduler{
        cron: cron.New(cron.WithSeconds()),
    }
}

func (s *Scheduler) Start() {
    s.cron.Start()
}

func (s *Scheduler) Stop() {
    s.cron.Stop()
}

// 添加任务
func (s *Scheduler) AddJob(spec string, job cron.Job) error {
    _, err := s.cron.AddJob(spec, job)
    return err
}

2. 任务定义

go
// internal/system/job/clean_logs.go
package job

type CleanLogsJob struct {
    logService *service.LogService
}

func (j *CleanLogsJob) Run() {
    // 清理30天前的日志
    j.logService.DeleteBefore(time.Now().AddDate(0, 0, -30))
}

3. 注册任务

go
// main.go
func initScheduler() *scheduler.Scheduler {
    s := scheduler.NewScheduler()
    
    // 每天凌晨2点清理日志
    s.AddJob("0 0 2 * * *", &job.CleanLogsJob{
        logService: service.NewLogService(),
    })
    
    // 每5分钟检查过期会话
    s.AddJob("0 */5 * * * *", &job.SessionCheckJob{})
    
    s.Start()
    return s
}

Cron 表达式

秒 分 时 日 月 周
*  *  *  *  *  *

示例:
"0 0 2 * * *"     # 每天凌晨2点
"0 */5 * * * *"   # 每5分钟
"0 0 9-17 * * 1-5" # 工作日9-17点每小时
"0 30 23 * * *"   # 每天23:30

异步任务

go
// 使用 goroutine + channel
type TaskQueue struct {
    tasks chan func()
}

func NewTaskQueue(size int) *TaskQueue {
    q := &TaskQueue{
        tasks: make(chan func(), size),
    }
    go q.worker()
    return q
}

func (q *TaskQueue) worker() {
    for task := range q.tasks {
        task()
    }
}

func (q *TaskQueue) Submit(task func()) {
    q.tasks <- task
}

任务状态持久化

go
// 存储到数据库
type JobLog struct {
    ID        int64     `gorm:"primaryKey"`
    JobName   string    `gorm:"size:100"`
    Status    string    `gorm:"size:20"`  // running/success/failed
    StartTime time.Time
    EndTime   time.Time
    Message   string    `gorm:"type:text"`
}

// 任务执行时记录
func (j *CleanLogsJob) Run() {
    log := &JobLog{
        JobName:   "clean_logs",
        Status:    "running",
        StartTime: time.Now(),
    }
    db.Create(log)
    
    defer func() {
        log.EndTime = time.Now()
        log.Status = "success"
        db.Save(log)
    }()
    
    // 执行清理
    ...
}

基于 MIT 许可发布