定时任务与延时处理
约 869 字大约 3 分钟
2025-03-03
平台业务周期任务通过 timedsvr 调度,处理器通过事件总线消费。这样能在管理端查看和调整任务,也避免把业务周期隐藏在某个 HTTP 进程的永久 ticker 中。
调度流程
业务服务注册处理器 → 创建分组/任务 → timedsvr 到点发布 → 工作池消费 → 业务幂等执行平台 SDK 位于 core/share/domain/timed。NewTimedSDK(client, bus) 接受任务管理客户端和事件订阅接口;ServiceContext 初始化一次并复用。
注册 Cron 任务
下面函数接收已装配的 SDK 和业务处理器,不依赖示例中的真实环境:
// 本文件注册演示业务的周期统计任务。
package startup
import (
"context"
timed "gitee.com/unitedrhino/core/share/domain/timed"
)
// RegisterHourly 注册按小时触发的统计任务;handler 自行处理统计窗口与幂等。
func RegisterHourly(ctx context.Context, sdk *timed.TimedSDK,
handler func(context.Context, map[string]string) error) error {
return sdk.RegisterCron(ctx, timed.CronTask{
GroupCode: "demo",
Code: "hourly-summary",
Name: "每小时汇总",
CronExpr: "0 0 * * * *",
Params: map[string]string{"window": "hour"},
Priority: 5,
Handler: handler,
})
}示例是含秒的六字段表达式。调度时区和实际触发时间需在本地环境确认,不能以服务器本地日期替代业务统计日期。
RegisterCron 先保存本地处理器,再幂等创建分组和任务。业务 startup 应处理 timedsvr 尚未就绪的注册失败,不能丢弃错误后永远不再注册。现有服务启动流程可参考 syssvr/aisvr 的任务注册实现。
启动顺序
- 建立数据库、任务客户端和 FastEvent。
- 创建 TimedSDK,注册所有任务及处理器。
- 调用
sdk.Start()注册消费订阅并检查错误。 - 确保 FastEvent 已启动,服务进入可用状态。
若当前服务已有统一启动流程,接入该流程,不额外启动第二套总线。任务主题由 server.timed.<groupCode>.<code> 生成,组与编码应稳定,不能随实例或版本随机变化。
延时任务
RegisterDelay(DelayTask{GroupCode, Code, Name, Handler}) 注册延时任务处理器。真正安排某次执行时,还要通过任务发送能力提交该次任务及参数;仅注册处理器不会自动产生一次延时执行。
同一任务处理器可接收多次业务触发,业务参数需要明确对象、所属企业及执行时间;不能把全部执行状态保存在进程内 map。
幂等与多实例
SDK 的运行中保护只覆盖当前进程。同组多副本、调度重试、故障恢复仍可能产生重复执行;以“企业 + 任务编码 + 统计窗口”等稳定键做唯一约束/幂等记录,长任务按需求使用分布式租约。
操作多企业数据时逐个绑定记录所属企业,不能沿用某次用户请求的身份。任务修改和暂停后的行为也要验证:数据库配置变更、已排队消息和已执行记录是不同状态。
验证
在本机隔离环境观察注册、触发、消费和业务结果四个环节。覆盖首次启动、重复启动、依赖延迟就绪、两副本、重复触发、进程中断恢复及无效参数;用数据库结果确认只执行了预期次数。
更新日志
2026/10/16 19:46
查看所有更新日志
b3b4d-docs(平台开发): 恢复有效专题并更新当前实现示例于
