Skip to content

[BUG][OPT-24] 为定时任务 start/stop 建立原子生命周期边界 #215

Open

Description

@Aias00

总览:#180

代码依据

问题与验收

ScheduledAgentTask.start/stop 使用独立 volatile started/stopped 标记,没有跨检查与调度操作的原子状态转换。并发 start 可都通过检查;stop 与 start 交错可能取消不到随后才发布的 future。调度抛错后的注册清理也需验证。

范围与验收

  • 使用 latch/barrier 和可控 TaskScheduler 复现双 start、start/stop 交错、stop-before-start、调度抛错与立即完成场景。
  • 明确 NEW/STARTING/RUNNING/STOPPING/STOPPED/FAILED 等等价状态契约,采用最小同步或 CAS 方案,不依赖多个布尔值拼接状态。
  • 同一任务至多一份有效调度;stop 完成后不会因为迟到的 future 发布而新增触发,注销和生命周期通知符合确定的幂等规则。
  • 明确 stop 是取消未来触发还是也请求取消在途执行;保持既有 cancel(false) 行为优先,若调整需单列迁移影响。
  • 启动失败无遗留注册/调度;保持已有一次性任务在 start 返回前完成的测试通过。
  • 与 OPT-23 同文件改动顺序合并,不混入任务持久化、分布式领取和业务重试策略重写。

本单对状态机和并发行为负责,不因修复要求所有 scheduler 支持热重启。

验证与兼容约束

Core 基线 f45b2cf。当前为静态代码分析,尚未运行本单针对性复现。先补有意义的行为测试,优先局部修复;公共 API/输出/调度语义变化需说明收益、影响、兼容替代、迁移成本及目标版本。修复不等待 Agent/Workflow/Loop 全局重构。

关联任务

Activity

  1. konlue commented on Nov 15, 2026

    @konlue
    Contributor

    您好,我想认领 #215。

    方案(把 start/stop 从双布尔拼接改为单一 CAS 状态机,全部落在 ScheduledAgentTask)

    • 根因四条:①并发双 start 都能通过 started 检查 → 两份调度;②stop 与 schedule 发布交错 → 迟到发布的 future 未被取消、继续触发;③stop 后再 start 竟可成功(stopped 标志不参与 start 检查);④start 调度失败(如 TaskRejectedException)→ started 仍 false 但构造器注册已发生 → 遗留注册。
    • 状态契约:嵌包私有 ScheduleState(NEW/STARTING/RUNNING/STOPPING/STOPPED/FAILED)+ AtomicReference CAS 转换,替换 volatile started/stopped。start 先 NEW→STARTING 占位:第二个 start 必被拒(恰好一份调度);STARTING→RUNNING 失败(stop 抢入 STARTING 窗口)→ 取消迟到 future 并以异常结束;调度抛错 → FAILED + 注销(启动失败不遗留注册)。stop 走单赢家 STOPPING(重复/并发 stop 幂等)→ 取消 future → 注销 → STOPPED。
    • 语义保持:stop 仍 cancel(false)(仅取消未来触发,不中断在途执行);isStarted/isStopped 派生语义与旧版一致(started 历史在停止后保留),[BUG][OPT-23] 定时任务应向实际注册的管理器注销 #214/[BUG][OPT-25] 调度管理器注册应与 shutdown 原子互斥 #216 既有测试零改动通过;不新增 listener 事件、不扩公共 API(枚举与 state() 观测点均包私有)。

    测试(新 ScheduledAgentTaskAtomicStartStopTest,latch 可控调度器做确定性交错,非概率压测)

    • 双 start:第一个 start 阻塞在调度发布窗口,第二个并发 start 被拒、只发布一份调度(修复前红:两份调度且无异常)
    • stop 后 start 被拒、不产生新调度(修复前红:start 成功并重新调度)
    • start 调度抛错:注销完成、原异常传播(修复前红:遗留注册)
    • STARTING 窗口内的 stop:迟到 future 被取消、任务终态 STOPPED(修复前红:future 存活 + start 成功进入 RUNNING)
    • 状态机全链 NEW→STARTING→RUNNING→STOPPING→STOPPED 断言
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions