任务调度
页面 /setting/job,实体 SysTask + SysTaskLog(按月分表)。它是框架 Tasks 调度引擎 的管理面:把任务定义落库、在页面上启停与手动触发,执行仍由框架的调度器完成。
数据模型
SysTask 的字段分四组:
标识与执行目标
| 字段 | 说明 |
|---|---|
TaskCode / TaskName / TaskDescription | 编码、名称、描述 |
TaskGroup | 分组,便于按业务域归类 |
TaskClass | 执行类的类型名——调度器据此解析出 IJobWorker |
TaskMethod | 方法名(按需) |
TaskParams | 参数(JSON 字符串),执行时注入上下文 |
触发方式
| 字段 | 说明 | 默认 |
|---|---|---|
TriggerType | Immediate / Cron / 间隔 等 | Immediate |
CronExpression | Cron 表达式(TriggerType 为 Cron 时用) | — |
IntervalSeconds | 固定间隔秒数 | — |
StartTime / EndTime | 生效窗口 | — |
RepeatCount | 重复次数上限,-1 表示不限 | -1 |
NextRunTime / LastRunTime / ExecutedCount | 运行时游标 | — |
前端用 CronExpression.vue 组件(输入框 + 可视化弹窗)编辑 Cron,不必手写表达式。
执行控制
| 字段 | 说明 | 默认 |
|---|---|---|
TimeoutSeconds | 单次执行超时 | 300 |
AllowConcurrent | 是否允许并发重入 | false |
RetryCount / MaxRetryCount | 已重试 / 最大重试 | 0 / 3 |
Priority | 优先级 | 0 |
RunTaskStatus | 运行状态(Pending / Running / …) | Pending |
Status | 启用状态 | Enabled |
启动时同步
Saas 模块在 OnPostApplicationInitialization(所有模块都就绪之后)做两件事:
- 扫描代码里声明式定义的任务;
- 把数据库中活跃的
SysTask同步进调度器。
同时复位崩溃残留的 Running 状态——进程被杀时正在跑的任务会永远停在 Running,既不会被再次触发(AllowConcurrent=false 时会被判为「已在运行」而跳过),也不会自己结束。不复位就等于这个任务从此再也不执行了。
新加的任务没跑起来
按顺序查:
Status是不是Enabled;TaskClass能不能解析到实际类型(改过命名空间/类名?);- Cron 表达式算不算得出下次时间——算不出时任务会「注册了但永不执行」,框架会打 Warning 日志,去日志里搜;
EndTime是不是已经过了、RepeatCount是不是已经用完;RunTaskStatus是不是卡在Running(崩溃残留没复位)。
并发与多实例
AllowConcurrent = false 依赖任务锁防止重入。跨实例防并发需要 Redis——框架的锁来自 Caching,未接 Redis 时退化为进程内锁,多实例部署会各跑各的。
生产多实例部署时这一点务必确认,否则会出现「日报表发了三份」这类问题。
多租户
任务执行时会切换到正确的租户上下文(ICurrentTenant.Change),解析优先级是:参数里的 tenantId → SysTask 的租户归属 → 当前异步上下文租户。宿主级任务的租户为空。
这意味着同一个任务类可以被不同租户各配一份,各自跑在自己的数据范围里。
执行日志
SysTaskLog(Sys_Task_Log_{yyyyMM},按月分表)记录每次执行的开始/结束、耗时、结果与异常。分表数据要走 SqlSugar 的分表 API 按时间范围查,不能当普通表直接查。
与其它异步机制的分工
| 需求 | 用什么 |
|---|---|
| 周期性/定时触发(每天凌晨跑报表) | 本页的任务调度 + SysTask |
| 一次性 fire-and-forget,入队即返回 | 框架 IBackgroundJobManager.EnqueueAsync |
| 持续拉队列消费、业务表做状态机 | XiHanBackgroundServiceBase<T> + IRedisDelayQueue<T>(发件箱、导出走这条) |
| 等人审批的长流程 | 工作流 |
相关页面
- 框架 · Tasks:调度引擎、中间件管道、声明式特性
- 缓存与异步:另外两条异步链路
- 数据模型:表结构
