# 5.19 定时任务调度机制 :::tip 概述 调度基于 robfig/cron:**调度器基础设施在 service 的 job 模块,任务实现集中放在 internal/task 包**,经 init 自注册、按任务记录的 url 字段数据驱动查找。配套执行锁、任务日志与管理界面。 ::: ## 架构分工 ```text internal/service/job*.go 调度器基础设施(cron 挂载/摘除/执行分派/执行锁) internal/task/*.go 任务处理方法(一任务一文件,init 自注册) service.DaemonInit 启动接线(cmd/api 在启动序列调用) cmd/api 空白导入 task 包 → 触发 init 注册 ``` 依赖方向单向:task → service(注册 + 共享能力),service 不反向依赖 task。 ## 任务实现契约 ```go // internal/task/xxx.go func init() { service.RegisterJobHandler("任务名", handler) // 注册名 = 任务记录 url 字段值 } // 处理方法签名 func(ctx context.Context, params string) (string, error) // params:任务参数(JSON 字符串,可为空) // 返回:写入任务日志摘要的文本 ``` **新增任务三步**:写 task 文件 → init 注册 → 管理界面建任务记录(url 填注册名 + cron 表达式)。不改调度器一行代码。 ## 内置任务 | 任务 | 职责 | |---|---| | LogClean | 按 `job.logRetentionDays`(默认 90 天)物理清理超期的操作/登录/任务日志(经 WithPhysicalDelete 放行) | | SendSms | 短信发送示例任务 | | HelloWorld | 演示任务 | ## 执行可靠性 | 机制 | 说明 | |---|---| | 执行锁 | 键 TTL `job.lockTTLSeconds`(默认 300 秒),执行期自动续期;长任务超时也不会被并发抢占 | | 任务日志 | 每次执行写 gin_job_log(开始/结束/耗时/结果/摘要) | | 失败处理 | 错误写入任务日志,不影响下次调度 | | 启动恢复 | DaemonInit 按数据库任务记录重建 cron 挂载 | ## 管理界面 任务管理页(monitor/job):任务 CRUD、cron 表达式配置、启停、手动执行、执行日志查看。见 [6.16 定时任务管理](/zh/modules/job.html)。 ## 配置 ```yaml job: logRetentionDays: 90 # 日志保留天数(LogClean 消费) lockTTLSeconds: 300 # 执行锁 TTL(任务参数可覆盖) ``` ## 优雅关闭 关闭链中"停定时任务"排在"关 DB"之前——任务可能还在写库,先停任务再关连接,避免执行期报错。 ## 下一步 → [第 6 章 业务模块](/zh/modules/user.html)