[062][调度模块]任务全生命周期管理 —— 从启动到追踪的完整闭环

简介: 本文详解调度模块任务全生命周期管理:涵盖启动/取消协调(ScheduleService)、三级数据聚合(DB+内存+运行态)、运行态安全校验及规格模式分页查询,实现高可用、强一致的任务闭环管控。(239字)

[062][调度模块]任务全生命周期管理 —— 从启动到追踪的完整闭环

本文章代码: gitee , gitcode , github

1. 任务启动与取消的核心协调器:ScheduleService

ScheduleService 作为应用层门面,协调 TaskRepository(持久化)和 ScheduleTaskManager(调度引擎)。

@Service
@RequiredArgsConstructor
public class ScheduleService {
   
    private final ScheduleTaskManager scheduleTaskManager;
    private final TaskRepository<?> taskRepository;

    public TaskExecutionDetails startTask(String taskCode) {
   
        Optional<? extends Task> taskOpt = taskRepository.findByTaskCode(taskCode);
        if (taskOpt.isPresent()) {
   
            Task task = taskOpt.get();
            scheduleTaskManager.createTask(task);  // 向调度器注册任务
            return buildDetails(task);             // 返回聚合详情
        }
        return null;
    }

    public TaskExecutionDetails cancelTask(String taskCode) {
   
        Optional<? extends Task> taskOpt = taskRepository.findByTaskCode(taskCode);
        if (taskOpt.isPresent()) {
   
            Task task = taskOpt.get();
            scheduleTaskManager.cancelTask(task.getTaskCode());  // 取消调度
            return buildDetails(task);
        }
        return null;
    }
}

关键设计:

  • 返回最新详情:启动/取消后立即返回 TaskExecutionDetails,方便 UI 即时反馈。
  • 容错处理:若 taskCode 不存在,返回 null(建议优化为抛出 TaskNotFoundException 或返回 Optional)。

2. 运行时详情聚合:buildDetails 的巧妙实现

private TaskExecutionDetails buildDetails(Task task) {
   
    // 1. 初始化 Builder,填充静态配置
    TaskExecutionDetails.TaskExecutionDetailsBuilder builder =
        TaskExecutionDetails.builder()
            .taskCode(task.getTaskCode())
            .classSimpleName(task.getClassSimpleName())
            .cron(task.getCron())
            .enabled(task.isEnabled())
            .description(task.getDescription())
            .metadata(MapUtils.unmodifiableMap(task.getMetadata()))
            .initialDelay(task.getInitialDelay())
            .maxExecutionCount(task.getMaxExecutionCount())
            .maxFailureCount(task.getMaxFailureCount())
            .dueDate(task.getDueDate());

    // 2. 覆盖内存中运行任务的实时配置(若任务正在运行)
    Task runningTask = scheduleTaskManager.getTask(task.getTaskCode());
    if (runningTask != null) {
   
        // ✅ 修正:必须复用 builder 实例,而非重新调用 builder()
        builder.taskCode(runningTask.getTaskCode())
               .classSimpleName(runningTask.getClassSimpleName())
               .cron(runningTask.getCron())
               .enabled(runningTask.isEnabled())
               .description(runningTask.getDescription())
               .metadata(MapUtils.unmodifiableMap(runningTask.getMetadata()))
               .initialDelay(runningTask.getInitialDelay())
               .maxExecutionCount(runningTask.getMaxExecutionCount())
               .maxFailureCount(runningTask.getMaxFailureCount())
               .dueDate(runningTask.getDueDate());
    }

    // 3. 填充最近一次执行状态(如运行中、成功、失败)
    TaskRuntimeData lastRuntimeData = 
        scheduleTaskManager.getLastTaskRuntimeData(task.getTaskCode());
    if (lastRuntimeData != null) {
   
        builder.taskStatus(lastRuntimeData.taskStatus())
               .lotNo(lastRuntimeData.lotNo())
               .totalCount(lastRuntimeData.totalCount())
               .totalFailureCount(lastRuntimeData.totalFailureCount())
               .startTime(lastRuntimeData.startTime())
               .endTime(lastRuntimeData.endTime())
               .message(lastRuntimeData.message())
               .throwable(lastRuntimeData.throwable());
    }
    return builder.build();
}

技术亮点:

  • 三级数据聚合:① 数据库持久化配置(基础)→ ② 内存运行实例(动态覆盖)→ ③ 最近执行状态(运行快照)。
  • 链式调用复用:通过复用 builder 变量,避免生成多个临时对象。

3. 运行态保护:修改/删除前的安全校验

JobEndpoint 中,更新或删除任务前必须检查是否正在运行:

@PutMapping("/{id}")
public ResponseEntity<JobVO> updateJob(@PathVariable Long id, @RequestBody JobUpdateDTO dto) {
   
    JobEntity job = jobService.findById(id);
    checkJobIsRunning(job.getTaskCode());  // 抛出异常若运行中
    BeanUtils.copyProperties(dto, job);
    return ResponseEntity.ok(JobVO.of(jobService.save(job)));
}

private void checkJobIsRunning(String taskCode) {
   
    if (scheduleTaskManager.isTaskRunning(taskCode)) {
   
        throw new ScheduleException("任务运行中,不能操作;请先取消任务");
    }
}

并发考量:此处存在 TOCTOU(Time-of-Check-Time-of-Use)问题,建议在 ScheduleTaskManager 层使用 ConcurrentHashMap 的原子操作或分布式锁(如 Redisson)。

4. 分页查询任务:规格模式的应用

@Data
public class JobQuery {
   
    private String taskCode;
    private String classSimpleName;
    private String description;

    public Specification<JobEntity> buildSpecification() {
   
        List<Specification<JobEntity>> specList = new ArrayList<>();
        specList.add(JobSpecification.taskCodeEqual(taskCode));
        specList.add(JobSpecification.classSimpleNameEqual(classSimpleName));
        specList.add(JobSpecification.descriptionLike(description));
        return specList.stream()
            .filter(Objects::nonNull)
            .reduce(Specification::and)
            .orElse((root, query, cb) -> cb.conjunction());  // 无条件时返回恒真条件
    }
}

技术亮点

  • 流式组合:通过 reduce(Specification::and) 链式拼接所有非空条件。
  • 默认全查询:若查询条件为空,返回 cb.conjunction()(即 WHERE 1=1),避免 null 异常。
目录
相关文章
|
2月前
|
算法 安全 Java
[047][Crypto模块]基于 Hutool 的常见加解密算法封装与密钥自动生成
本文基于Hutool封装统一加解密框架,提供AES/RSA/SM2/SM4/HMAC等算法的`CryptoProcessor`标准接口,支持密钥自动生成与动态切换,解耦业务代码,兼顾国密合规与易用性,提升安全性与可测试性。(239字)
134 1
|
27天前
|
JSON 人工智能 Java
【AI】Agent 全栈进阶|工具调用与结构化输出
文章介绍了大模型的关键能力——Function Calling(函数调用)与结构化输出,主要包含四部分内容: Function Calling 原理,工具定义与注册,JSON Schema 约束输出,最小工具调用循环
139 2
|
27天前
|
JSON 自然语言处理 小程序
节假日查询-假期信息查询 API 接口文档教程
本文为开发者与系统工程师提供阿里云「法定节假日查询」API的权威接入指南,涵盖单参数调用、调休补班识别、多语言示例、免费试用及透明计费等核心能力,助力电商、HR、金融、ERP等场景快速实现假期自动化识别。
181 0
节假日查询-假期信息查询 API 接口文档教程
|
27天前
|
人工智能 数据安全/隐私保护 自然语言处理
阿里云百炼AI通用型节省计划、资源包、Token Plan三种计费方式详解与选型指南
本文介绍了阿里云百炼平台三大核心计费模式的底层差异与选型策略。AI通用型节省计划通过承诺月消费换取阶梯折扣,最高5.3折,覆盖阿里直供全模型,适合长期稳定的多模型混合使用场景;资源包为预付费固定资源量方案,仅支持单一指定模型,灵活性低,适配短期测试、单一模型轻量使用场景;Token Plan采用统一Credits订阅制,全模型通用且支持团队席位管理,成本可控,适合新用户入门试水。文章结合抵扣优先级、适用场景与最新优惠活动,为不同规模的企业和开发者提供精准降本选型指南。
阿里云百炼AI通用型节省计划、资源包、Token Plan三种计费方式详解与选型指南
|
27天前
|
Arthas 监控 Java
阿里程序员常用的 15 款开发者工具!
阿里巴巴将自身在各类业务场景下的技术积淀,通过开源、云上实现或工具等形式对外开放,本文将精选了一些阿里巴巴的开发者工具,希望能帮助开发者们提高开发效率、更优雅的写代码。
280 1
|
27天前
|
搜索推荐 Linux API
趁 DeepSeek Harness 刚火,我做了一个 DSH 插件市场,2 天冷启动记录
DeepSeek Harness 插件生态分散难用?DSH Marketplace(dshmarketplace.dev)应运而生:聚合插件、标注兼容性、提供一键安装。支持Web/CLI/Python/API/DSH内置Store等多入口,含自托管插件。开源共建,欢迎用户反馈与作者入驻。(239字)
|
27天前
|
人工智能 JavaScript 测试技术
从 0 到 1,DeepSeek Harness 保姆级安装与使用教程!
DeepSeek Harness是DeepSeek推出的开源Agent运行框架,秉持“一切皆插件”理念,支持模型、工具、技能、工作流等全模块自由替换与扩展。其核心Cordis内核实现动态插件管理,赋能Agent自进化。已成GitHub史上增速最快开源项目(15w+ Star),标志着国内大模型从拼价格转向重架构与生态的新拐点。
1559 6
从 0 到 1,DeepSeek Harness 保姆级安装与使用教程!
|
2月前
|
前端开发 Java API
[049][Crypto模块]前后端混合加密API实战:基于Spring Boot的AES+RSA安全传输方案
本文详解Spring Boot中AES+RSA混合加密实战:前端用RSA公钥加密随机AES密钥并传输,后端通过`@Crypto`注解自动解密请求体。涵盖公钥分发、Hex/Base64编码统一、ECB模式适配及Caffeine缓存优化,提供开箱即用的端到端安全传输方案。(239字)
254 0
|
4月前
|
运维 Java 开发者
[015][web模块]基于Spring Boot的HTTP客户端日志与默认配置实战
本文详解基于Spring Boot的HTTP客户端统一配置方案,支持RestTemplate、RestClient与WebClient三种客户端,实现无侵入的日志记录(请求/响应头、状态码)、默认请求头注入(如X-Request-Id)、非2xx异常自动转换及链路追踪支持,全部通过Customizer与Filter机制自动装配,开箱即用,提升微服务调用可观测性与开发效率。(239字)
356 5
[015][web模块]基于Spring Boot的HTTP客户端日志与默认配置实战
|
2月前
|
人工智能 运维 安全