package com.ruoyi.common.core.service; import com.ruoyi.common.core.service.dto.VisitScheduleRollResultDto; import java.util.List; /** * 循环任务组「轮次滚动」能力的预留接口(第 9 步)。 * *

为什么这个接口是"粗粒度"的(重要设计说明)

* 任务组滚动的核心动作要做一次 {@code ServiceSubtask} 的全字段深拷贝: *
 * ServiceSubtask copy = JSON.parseObject(JSON.toJSONString(src), ServiceSubtask.class);
 * copy.setId(null); copy.setSenduuid(null); copy.setResult(null); ...
 * 
* 而 {@code ServiceSubtask} 有 116 个字段。 *

* 如果为了"把逻辑搬进新模块"而在模块间传一个 116 字段的 DTO,字段映射本身就是巨大风险面, * 且换不来任何收益 —— 全字段拷贝的语义由 JSON 序列化保证,不需要逐字段搬运。 *

* 所以本接口刻意切成两个动作,把"原子性"留在实现侧: *

    *
  1. {@link #selectActiveCycleSchedules(int)} —— 查一批待评估的循环计划;
  2. *
  3. {@link #rollOneSchedule(Long)} —— 滚动单个计划(整个动作原子完成,含深拷贝与推进)。
  4. *
* 调用方({@code ruoyi-inhospvisit} 的 {@code TaskGroupCycleRoller}) * 负责"批次上限 + 逐条 try/catch + 计数与日志"这部分编排逻辑。 *

* 这与其它端口({@code VisitTaskCreateApi} 等)的粒度不同,是有意的: * 那些端口的对象字段少、映射可控;这里的对象有 116 个字段、且语义是"整体克隆"。 * *

与 {@code ServiceTaskScheduleServiceImpl#rollCycleTasks} 的关系

* {@code rollCycleTasks} 的实现本次刻意保留在 smartor 不动(它仍被 * {@code RyTask.rollTaskGroupCycle} 调用,而改调用点在第 10 步)。 * 本接口的实现(过渡 Bridge)与它共享同一套底层能力(同一个 Mapper、同一份深拷贝语义), * 不复制业务逻辑;等到第 10 步把调用点切过来后,{@code rollCycleTasks} 才退役。 * *

⚠️ 过渡期禁止双跑

* 第 9 步做完后,「老的 {@code rollCycleTasks}」与「新的 {@code TaskGroupCycleRoller}」 * 不能同时被调度 —— 两边都会"推进轮次 + 新建 subtask",双跑会造成重复轮次。 * 第 10 步会把 {@code RyTask} 的方法体切到新路径;在那之前,新路径只被自检程序调用。 */ public interface ScheduleRollPort { /** * 查一批待评估的循环计划(原 {@code ServiceTaskScheduleMapper#selectActiveCycleSchedules})。 *

* 该查询自身的条件({@code schedule_style = 1}、{@code max_loop_count} 上限等)在 * smartor 的 XML 里,本次照抄不动,由实现侧保证。 * * @param limit 批次上限(原实现固定 200) * @return 计划ID列表;无数据返回空列表 */ List selectActiveCycleSchedules(int limit); /** * 滚动单个计划:若"本轮已全部结束"则推进到下一轮并克隆 subtask。 *

* 逐行对应原 {@code ServiceTaskScheduleServiceImpl#rollOneSchedule}(L196-280),包括: *

* 整个动作必须在实现侧一次性完成(含事务),不能拆成"取模板→改→存"三步跨模块调用。 * * @param scheduleId 计划ID * @return 滚动结果({@code rolled=false} 时 {@code skipReason} 说明原因) */ VisitScheduleRollResultDto rollOneSchedule(Long scheduleId); }