scaffold-job 任务调度模块

模块概述

scaffold-job 基于 Quartz 核心思想实现的轻量级任务调度框架。采用 SPI 架构,业务模块只需实现 JobHandler 接口并使用 @JobHandler 注解注册,即可被调度引擎自动发现和执行。支持 Cron 表达式调度、手动触发、任务暂停/恢复、失败重试、分布式锁(依赖 Redis)等能力。

功能列表

  • Cron 调度:支持标准 Cron 表达式,应用启动时自动加载所有正常状态的任务
  • 手动触发:支持通过 API 立即触发任务执行
  • 任务生命周期管理:创建、更新、删除、暂停、恢复
  • 失败重试:可配置重试次数和重试间隔
  • 分布式锁:非并发任务使用 Redis 分布式锁保证单节点执行
  • 执行日志:完整记录每次执行的状态、耗时、执行主机、traceId
  • 超时控制:可配置任务超时时间

核心组件

类名 职责
Controller JobInfoController 任务管理接口,路径 /v1/job/info
Controller JobLogController 执行日志接口,路径 /v1/job/log
Service JobInfoService 任务的增删改查、触发、暂停、恢复
Service JobLogService 执行日志的查询
Core JobScheduler 调度引擎,管理 Cron 注册/取消/生命周期
Core JobExecutor 任务执行器,负责锁获取、日志记录、重试、执行
SPI JobHandler 任务处理器接口,业务模块实现
SPI JobContext 执行上下文(任务ID、名称、参数、重试序号等)
SPI ExecuteResult 执行结果(成功/失败、消息)
SPI JobHandlerRegistry 处理器注册中心,自动扫描 @JobHandler 注解的 Bean
Annotation @JobHandler 标注在处理器类上,声明处理器名称
Entity JobInfo 任务信息实体
Entity JobLog 执行日志实体
Config JobAutoConfiguration 自动配置类
Config JobProperties 配置属性类
Config JobSchedulerConfig 调度线程池配置

配置参数

配置前缀:scaffold.job

参数 类型 默认值 说明
enabled boolean true 模块开关
poolSize Integer CPU核数 * 2 调度线程池大小
threadNamePrefix String job-scheduler- 线程名前缀

枚举值说明

枚举 说明
JobStatusEnum.NORMAL 0 正常(可调度执行)
JobStatusEnum.PAUSED 1 暂停
JobStatusEnum.DISABLED 2 禁用
MisfirePolicyEnum.EXECUTE_NOW 1 立即执行
MisfirePolicyEnum.EXECUTE_ONCE 2 执行一次
MisfirePolicyEnum.IGNORE 3 忽略
TriggerTypeEnum.CRON 1 Cron 触发
TriggerTypeEnum.MANUAL 2 手动触发
JobLogStatusEnum.RUNNING - 执行中
JobLogStatusEnum.SUCCESS - 成功
JobLogStatusEnum.FAILED - 失败

注意JobStatusEnumJobLogStatusEnum 为多态状态机,不遵循布尔语义规范。

API 接口列表

任务管理 /v1/job/info

方法 路径 说明
POST /create 创建任务
POST /update 更新任务
POST /delete/{id} 删除任务
GET /get/{id} 任务详情
GET /page 任务分页查询
POST /trigger/{id} 手动触发任务执行
POST /pause/{id} 暂停任务
POST /resume/{id} 恢复任务

执行日志 /v1/job/log

方法 路径 说明
GET /page 执行日志分页查询
GET /get/{id} 执行日志详情

SPI 扩展点

JobHandler 接口

业务模块实现此接口,配合 @JobHandler 注解注册到调度引擎。

public interface JobHandler {
    ExecuteResult execute(JobContext context);
}

JobContext 上下文字段

字段 类型 说明
jobId Long 任务ID
jobName String 任务名称
params String 任务参数
retryIndex int 当前重试序号(0=首次执行)
logId Long 执行日志ID
traceId String 链路追踪ID

ExecuteResult 工厂方法

方法 说明
ExecuteResult.success() 返回成功结果
ExecuteResult.success(message) 返回成功结果(含消息)
ExecuteResult.failure(message) 返回失败结果(含错误信息)

使用示例

实现一个定时任务处理器

@Slf4j
@JobHandler("orderTimeoutChecker")
@Component
public class OrderTimeoutJobHandler implements JobHandler {

    private final OrderRepository orderRepository;

    @Override
    public ExecuteResult execute(JobContext context) {
        log.info("开始检查超时订单, params={}", context.getParams());

        int count = orderRepository.cancelTimeoutOrders();

        return ExecuteResult.success("取消超时订单 " + count + " 笔");
    }
}

通过 API 创建定时任务

const { data } = await post('/v1/job/info/create', {
  jobName: '超时订单检查',
  handlerBean: 'orderTimeoutChecker',
  cronExpression: '0 */5 * * * ?',
  params: '{"timeoutMinutes": 30}',
  retryCount: 2,
  retryInterval: 10,
  concurrent: 0,      // 不允许并发
  misfirePolicy: 1,   // 立即执行
  timeout: 300         // 超时 300 秒
})

手动触发和暂停任务

// 手动触发
await post(`/v1/job/info/trigger/${jobId}`)

// 暂停任务
await post(`/v1/job/info/pause/${jobId}`)

// 恢复任务
await post(`/v1/job/info/resume/${jobId}`)

注意事项

  • @JobHandler 注解的 value 值必须与 t_job_info 表的 handler_bean 字段一致。
  • 应用启动时 JobScheduler 自动加载所有 status=0(正常)的任务并注册 Cron 调度。
  • 非并发任务(concurrent=0)使用 Redis 分布式锁,依赖 scaffold-redis 模块。
  • 任务执行支持失败重试,重试次数和间隔在 JobInfo 中配置。
  • 执行日志记录了执行主机、traceId,便于问题排查。
  • 删除任务会同时取消其 Cron 调度。
  • 模块启用条件:scaffold.job.enabled=true(默认启用)。
  • 状态枚举JobStatusEnumJobLogStatusEnum 为多态状态机,不遵循布尔语义规范(status=0 表示正常,这与布尔语义规范不同,保留原有值)