myxce/docs/left_scheduler_work.md
lei.chen d4b98aab01 docs: scheduler reconnect — confirmed real heap corruption (ASAN + debug both crash)
Deep-dive: the rejoin works but crashes ~3-8s later with a REAL heap corruption
(ASAN bad-free freeing a pointer 56B into a 60B region, all-loader frames;
non-ASAN debug build aborts with free(): invalid pointer, gdb stack corrupted).
The endpoint-unmonitor fix (correct, matches xce_ctx_stop) did not help.
Candidate roots: config re-push re-running sched_init_config non-idempotently
(sharedInst MOVE_PTR/zarray_put), lib reconnect vs in-flight vtask, or
state-resync merge. All scheduler reconnect changes reverted to keep the
scheduler stable; this is a dedicated deep-debugging task.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-14 03:09:04 +00:00

21 KiB
Raw Blame History

Scheduler 剩余工作清单(left_scheduler_work)

  • 状态:持续更新
  • 日期:2026-08-13
  • 来源:项目自带 MD 设计文档分析(.kiro/steering、.kiro/specs、docs/、CLAUDE.md)

本文汇总 scheduler 相关的一切剩余/未完成/已知损坏的工作,按优先级排序。每项标注来源文档与状态。


一、最紧急:当前影响集群的 bug

1. bug-1494 — 作业全部 PEND 不调度【已修复,2026-08-11】

  • 状态:已解决(两个子问题均已修复并集群验证)。
  • 来源:CLAUDE.md、docs/Scheduler-Agent-设计文档.md §10.2b
  • 子问题一(已修复,commit 6928f74,bug-1510):scheduler 在 worker 未就绪(down/joining)时派发,controller 拒绝(dispatch_a_job_ worker t1 status=0x10000 ep nil)并回 jobDispatchFail 通知,但 scheduler 的 sched_handle_notify 无此 case(丢弃)→ 作业保持 RUN 视图永不重选 → 永久 PEND(worker 恢复也不派发)。修复:handler.c 加 jobDispatchFail case + sched_requeue_pend_job()(重置 PEND + 重新入 fcfs pendJobs)。
  • 子问题二(已修复,commit 1a2bd3f):controller 重启 / worker 死亡后,scheduler 资源视图 slots=0 → 无法派发。根因:worker 死亡时 mark_worker_unavail 正确清零 slots=0;worker 重新 join(slots=8)时 controller 推送新 worker,但 scheduler 的 sched_update_workers → sched_add_worker 用 key_add 遇 EEXIST 丢弃新 worker,scheduler 永久保留旧的 slots=0 → PEND 作业永不派发。修复:sched_update_workers 对已存在 worker 就地更新(交换新 resvals/resInUse/status,释放旧对象),并 NULL-guard make_sched_worker。集群验证:scheduler 在 worker 死亡时启动(slots=0)→ worker 重新 join(slots=8)→ 之前卡住的 PEND 作业全部派发完成,无 ASAN。
  • 子问题三(已修复,commit e4aaef4,bug-1512,2026-08-13):多 worker(t1/t2/t3)下作业重复派发/过派发,分布严重不均。根因:controller handle_jobdispatch 对成功派发也发 jobDispatchFail 通知(code=0 是成功 ack,else 分支 notify_dispatch(jobid, 0));scheduler sched_handle_notify 无 code 判断(bug-1510 修复引入),把成功 ack 也当失败 → 每个成功派发的作业立即 re-PEND → 下次 session 重选 → 再派发,原实例继续跑 → 重复实例(3 worker 上 24 个作业跑出 38 个实例,堆积在 t1)。修复:fail->code >= 0 当成功 ack no-op 消费(作业已在 commit 标记 RUN),仅 code < 0 才 sched_requeue_pend_job。集群验证(新 scheduler 部署 t1):24 个 sleep-300 作业均匀 8/8/8 分布、零重复、全部 DONE;dispatchFail 日志 38→0;新单测 test_handle_dispatch_fail_requeues_only_on_negative_code + 原 15 测试全过。
  • 关联:scheduler 运行时重连(component-failover-adoption)仍为独立待办——scheduler 本身不会在 controller 重启后自动重连,需手动重启(但重连后 slots 恢复正常)。sched_try_alloc_on_hosts 只试 worker group member 0(resource.c FIXME)在 worker 名互异时休眠,同名冗余 worker 场景仍需处理。
  • 临时恢复:不再需要(worker 重新 join 即可恢复 slots)。

2. bug-1490 — apiserver control HTTP 500【已修复,2026-08-07】

  • 状态:已修复
  • 来源:CLAUDE.md、Scheduler-Agent-设计文档.md §10.2b
  • 根因(两个叠加缺陷):
    1. array_idx 类型断言 panic → HTTP 500:validateJobControl/foundJob 用 jobinfo.Data["array_idx"].(int64),但 StoreToOrderMaps 产出的是 int(JobInfo.ArrayIdx 声明为 int)→ panic → Gin Recovery → HTTP 500 → 请求到不了 controller。
    2. jobctrl 联合判别符错误 → -EINVAL:backend.ControlJob 把 xce_jobctrl_t.action 设成 models.JOB_*(1/2/3/8),但该字段是 capnp JobControl union 判别符(JobControl_u_siginfo=0/JobControl_u_ckptoption=1)→ controller job_ctrl() 走错分支(default)→ 每个动作都 -EINVAL。
  • 修复:normalizeJobInt64/jobArrayIdx 辅助函数 + jobCtrlDiscriminant 映射。单测 5 个(controllers 3 + backend 1 + 顺带修了 pre-existing 的 backend cgo 测试编译)。集群 E2E 验证:hold→PSUSP、release→PEND、cancel→EXIT,无 500 无 -EINVAL,全部 daemon 健康。
  • 顺带修复:resolveExecUser 被放在 //go:build cgo 的 convert.go 里导致 make test(CGO_ENABLED=0)下 backend 包编译失败——移到纯 Go 的 convert_pure.go。

3. bug-1489 / bug-1491 — 已修复(上下文)

  • bug-1491 OrderMap 列格式解析修复(2026-08-01,httpclient.go)
  • bug-1489 whitelist 缺 /xce/v1/apikeys 修复(2026-08-01,middleware/whitelist.go)

二、scheduler-controller-msg-gap:已实现但有已知缺陷

spec 声称 36/36 任务完成,但 re-audit(research.md)发现缺陷。来源:.kiro/specs/scheduler-controller-msg-gap/research.md。

项 严重度 描述
G-8 HIGH sched_update_existing_job 是死代码。notify 驱动的作业更新走 bulk sched_update_jobs() 的 CREATE 路径(make_sched_job 新建),损坏/复制作业状态。很可能与 bug-1494 相关。Req 3 UB-3.1/3.2 未满足。
G-3 MED 5 个新 op 的 payload(UPDATE_QUEUE/UPDATE_RESOURCES/UPDATE_RESVALS_FULL/UPDATE_RESVALS/JOB_RUSAGE)在 sched_pend_update_killer 里 break; 从不释放——长驻 daemon 慢速泄漏。
G-5 MED xce_sched_job_t 无 rusage 字段。JOB_RUSAGE case 只调插件 hook 就丢 payload。UB-6.1 未满足。
G-4 LOW 即使修好 G-8 让 sched_update_existing_job 可达,它也只在作业上应用 state——priority/queue/resreq 未应用。
G-6 TODO 任务 9.2/9.3/9.4/9.6/9.7 勾了 [x] 但测试缺失/部分;9.5 测的是本地 stub 非真 schedobj.c。
G-7 TODO 文档漂移:design 说 xce_sched_op_name 在 lib/helper,实际是 scheduler.c 里 static sched_op_name。
R-3 休眠 Req 1 处理器前瞻实现,但 controller 当前不推送 Data_data_resources/resvals 表给 scheduler——生产未触发。

三、核心调度引擎重构(scheduler-framework 家族:spec 有、零实现)

来源:.kiro/specs/scheduler-framework/、scheduler-core/、scheduler-allocation/、scheduler-preemption/(均只有 requirements/brief,无 design/tasks)。roadmap 显示 "Next: /kiro-spec-requirements scheduler-framework"。

scheduler-core(Phase 1-3)

项 描述
可插拔 picker 接口 替代硬编码 "xce_sched_fcfs" 字符串,job_pick_plugin 字段 + config 加载 + 每 queue 覆盖。核心循环调 picker->next_job()。
builtin_fcfs 默认实现 MUST/SHOULD hook 全实现,私有 ordq_t 状态,排序同现状(跨 queue priority desc,队内 priority desc + queue_time asc)。
无回归保证 HA soak 必须验证作业挑选顺序零偏差。
core/driver 分离 提取 xce_sched_core_t,无 mode flag,虚拟时钟 xce_core_now(),决策回调。Phase 2。
模拟模式 JSONL/.replay 重放 + 虚拟时钟 + snapshot/restore + 确定性重放 + xceadmin scheduler record + --sim/--sim-verify/--interactive。Phase 3。
等价保证 "记录实跑 → 模拟重放 → 决策字节级一致"(AC 7.1)。

scheduler-allocation

项 描述
惰性 plan 迭代器 xce_alloc_plan_iter_t:init(resreq)/next()->plan/fini(),cancel-safe。
惰性 host 迭代器 xce_host_iter_t:init(plan, workers)/next()->worker,复用现有 select 表达式求值器。
parjob 组合分配 替换 stub return 0:1host×N、2hosts×ceil(N/2)、…、Nhosts×1。
会话级 resreq 缓存 keyed on {minTasks,maxTasks,select_node_id,rusage_hash,user,queue,project},作业 ingest 时预计算。
seqjob 重包 1host/1slot 走同一迭代器接口,验证抽象。

scheduler-preemption

项 描述
XCE_DECISION_PREEMPT decision.h 新 opcode + xce_preempt_decision_t(victim_jobids, SIGSTP, preempting_jobid)。
victim 选择策略 默认 "lowest_priority_first",LSF 式跨 queue(preemptible_queues),最小足够 victim 集,安全护栏(不抢占同/高优先级、非抢占 queue)。
SIGSTP 管线 scheduler→controller→worker→SIGSTP 进程组,作业→JOB_SUSPENDED,复用 HOOK_DETAIL_JOB_STOP。每 queue preemptible/preempt_policy/preemptible_queues 字段。
核心循环集成 分配失败后、pending 前:can_preempt → 选 victim → 发 PREEMPT → preempting 作业下一轮再派(异步抢占)。
后续推迟项 SIGKILL+requeue 升级、JOB_SUSPENDED resume 机制。

四、故障转移 / 重连

component-failover-adoption(14 任务:部分完成,2026-08-14)

  • 来源:.kiro/specs/component-failover-adoption/
  • 关键结论:requirements.md Background 明确 "scheduler 没有任何运行时重连/rejoin 逻辑——连的 controller 死后,scheduler 无法切换到其他候选"。
  • ✅ 已完成并集群验证(commit 2165b1a):
    • worker 无限重试(controller_connector.c checking_connection):去掉 5 次上限,无限重试直到重连(连接器线程专用,不阻塞硬件/进程监控线程)。实测:杀 controller 后 3 worker 全部存活并持续重试,controller 回来后自动 rejoin。
    • apiserver rejoin(clib.go StartHeartbeat + xce_backend_rejoin):心跳从失败转成功时显式 rejoin(HostRole_apiserver),恢复 push 通知。实测:controller 重启后日志 backend re-joined controller after reconnect。
  • ❌ scheduler reconnect 被真实 heap corruption 阻塞(未合入,已回退):
    • scheduler 的 rejoin(xcecli_set_reconnect_handler flag + 主循环 xcecli_join)功能上能重连并 rejoin(实测收到 config push),但 rejoin 后 ~3-8s 崩溃。
    • 诊断(2026-08-14 深入):ASAN 报 bad-free(释放 60 字节区域偏移 56 处的指针,...66b8,分配线程 T4/释放线程 T5,全栈在 loader);debug 非 ASAN 构建同样崩(free(): invalid pointer + core,gdb 显示 malloc_printerr 后栈被破坏)——真实堆损坏,非 ASAN 假象。
    • 尝试的修复(均无效):xce_ctx_reconnect 先 iomgr_unmonitor 再 endpoint_fini(对齐 xce_ctx_stop 的安全拆除,正确但不充分)。
    • 候选根因:(a) rejoin 触发 config 重推 → sched_init_config 非幂等重跑(sharedInst 的 MOVE_PTR/zarray_put killer 覆盖、queues/resources 重加);(b) lib reconnect 与 vtask 并发处理旧 endpoint;(c) 重新同步时 scheduler 本地状态与重推的 merge 缺陷。栈被破坏无法干净回溯,需 valgrind/隔离测试定位。
    • 修法:独立深层调试任务(scheduler 状态重同步幂等性 + lib reconnect/vtask 生命周期)。为保持 scheduler 稳定已回退全部 reconnect 改动。
  • 剩余任务(scheduler reconnect + 多 controller E2E + apiserver 电路熔断等)见 spec。

P2.5

  • 来源:product.md:35、docs/superpowers/plans/2026-05-07-p25-discovery.md
  • product.md 标 P2.5 "In progress";P2.5-6 描述 scheduler --peers/--ca-cert CLI 更新;P2.5-7(CGo bridge)推迟。是否全完成文档不确定。
  • 注意:P2.5 与 component-failover-adoption 用了两套技术路径(xce_connect_cluster 裸 endpoint vs xcecli_ctx_t/XCECLI_FAILOVER_CALL),文档未调和。

五、scheduler agent / MCP server(Phase 2-4)

来源:docs/Scheduler-Agent-设计文档.md

项 状态 描述
Phase 2:SSE 事件流 计划 apiserver SSE endpoint + EventBroker,schedulerclient WatchJobs(),mcp-server 接入。ADR-004 设计完成待实施。估 2-3 天。
Phase 3:LSF adapter 计划 CLI 解析优先,Python Sidecar 后续。估 +1 月。
Phase 4:Slurm + K8s 计划 slurmrestd + CLI fallback;client-go。估 +1 月。
modify 工具 推迟 apiserver 当前无 modify 端点(control 仅 kill/stop/resume/checkpoint),需新增后端端点。
未决决策 未解决 LLM 模型选型(Claude API/自建/混合);多集群 URM 源识别;air-gapped LLM 访问。

六、roadmap / 加固项

项 状态 描述
调度决策过 commit barrier 计划 DISPATCH/PEND/PREEMPT 需过 majority commit barrier。多文档提及为独立加固项,从 scheduler-framework scope 推迟。
worker-rejoin-resync backlog worker 重连重报运行/完成作业状态(bug-396 兜底)。依赖 ha-consistency-invariants。scheduler 间接受影响(恢复作业需调度状态核对)。
entity-bearing snapshots backlog 解锁 config-upgrade-snapshot、基于快照的状态传输。影响 scheduler 模拟(snapshot/restore)。COW 机制存在但休眠。
project-resource-ownership 未来 spec 层级项目树 + 资源配额,project-aware picker 插件,queue↔project 映射。核心循环零改动(只加新 picker)。
perf-tuning-extraction / clusterconfig-schema-split 计划 配置 schema 变更触及 scheduler 配置摄取。
bulk job-array query/cancel 推迟 依赖 job-array-single-wal-record。

七、文档空白(设计层面没人写过)

  1. 调度决策 commit barrier 细节——roadmap 只提了标题,无 spec/design。
  2. scheduler 状态在 controller failover 后如何同步——全量重推?增量?文档沉默。roadmap:67 提到 lightweight rejoin re-attach(当前是 full-state rejoin,"大但罕见")。
  3. scheduler 模拟模式 vs controller WAL replay 关系——failover 后 scheduler 从 controller WAL 重放还是收新状态推送?未讨论。
  4. core/driver 分离下的对象内存/生命周期——三线程(picker/allocator/driver)async 生产者/消费者模型下借用指针的归属未细化。
  5. 无 scheduler 专属 HA soak 测试——多次提到 "HA soak regression" 但无 /xce-test-ha 变体专门跑 scheduler failover/reconnect。
  6. src/scheduler/CLAUDE.md 太薄——约 25 行,无 spec 状态、无已知 bug 清单、无剩余工作节。建议补全(对照 src/controller/CLAUDE.md)。
  7. scheduler 与 raft/TLA+ 架构整合——raft 系列落地后 scheduler 与 log/commit 模型的交互未讨论。

八、scheduler-agent(chatbot / AI 辅助)剩余工作

  • 状态:持续更新
  • 日期:2026-08-07
  • 来源:docs/Scheduler-Agent-设计文档.md(v1.2,权威设计文档)、src/docs/chatbot-verification.md、src/frontend/CLAUDE.md、CLAUDE.md
  • 注意:feature 直接从设计文档实现,未走 .kiro spec 流程(.kiro/specs/ 无 scheduler-agent/chatbot spec)。/home/lchen/code/chatbot/ 是 XCE 完整镜像工作树,代码两份一致。

架构与现状

用户自然语言 → Claude Code(LLM)→ MCP stdio → mcp-server → schedulerclient → apiserver REST → controller(C 后端)。不是独立聊天组件,而是自然语言调度管理 Agent 框架。

已完成:

Phase 内容 状态
Phase 0 只读 MCP Server:6 读工具、schedulerclient、mcp_readonly 角色、API Key 认证 ✅ 2026-07-26
Phase 1 4 写工具(submit/cancel/hold/release)、general_serial 模板、mcp_operator、dry_run 审查 ✅ 2026-08-01(代码);2026-08-12 完整集群 E2E 验证通过:submit→运行→DONE、cancel(kill)→EXIT、读接口全通。注意:job control 动作是 kill/stop/resume/checkpoint(schedulerclient 已正确映射)
Phase 2 SSE 事件流(/xce/v1/events + EventBroker)+ WatchJobs() + 4 高级工具 ✅ 2026-08-12 实施并集群验证(见下)

Phase 2 落地明细(2026-08-12):

  • apiserver:/xce/v1/events SSE endpoint + backend.Broker(EventBroker,DefaultHandler 发布 job.created/updated/deleted/finished);RBAC event:view(mcp_readonly/mcp_operator/cluster_admin);whitelist 加 /xce/v1/events。
  • schedulerclient:WatchJobs(ctx) 订阅 SSE 流;顺带修复 ListJobs 的 filter 参数——apiserver 用 filter=queue_name:eq:...(field:op:value),原 queue_name/submit_user 参数被 400 拒绝(影响带过滤的列表 + estimate_wait_time)。
  • mcp-server:14 工具(10 原有 + scheduler_wait_job/scheduler_analyze_failure/scheduler_suggest_resources/scheduler_estimate_wait_time)。
  • 人类可读 jobid(2026-08-13):apiserver 响应加 job_id_human/human_id(cluster-apiserver-时间戳-序号,如 1-0-1786585485-0),复用 backend.FormatJobID——MCP 原来只返回裸 64 位数字(73930964699447296),xce_test/xcecli 只认连字符格式,导致跨工具无法引用。架构原则:apiserver 负责数据正确性,mcp-server 只读取透传。
  • Claude Code 集成:.mcp.json 注册 xce-scheduler server,key 用 ${XCE_API_KEY} 环境变量(不硬编码提交);apiserver 重启后 key 失效需重新生成。

注意:apiserver 在 controller 重启后不会自动重新 join(只重连 TCP,DataStore 保持陈旧为空)——controller 重启后需手动重启 apiserver 才会重新收到作业推送。这与 scheduler/worker 的重连缺口同类,属 component-failover-adoption 待办。

代码:src/frontend/mcp-server/(14 工具)、src/frontend/schedulerclient/(~50 测试)、apiserver API Key + RBAC + SSE 支持。

1. 阻塞性 bug(影响 chatbot E2E 验证)

Bug 影响
bug-1490 ✅ 已修复(c90e63e)。MCP 写工具(submit/hold/release/cancel)集群 E2E 验证通过;scheduler_get_job 的 CompConditions 过滤 bug 也已修复(0572740)。另修了部署缺口:/opt/xce/config 缺 rbac.yaml 导致 mcp API key 全 403
bug-1494 作业全 PEND 不调度,Agent 提交流程无法完成。已修复(2026-08-11):子问题一 dispatch-fail 重试(bug-1510)+ 子问题二 worker 重新 join 后 slots 不更新(见第一节)
chatbot 过度建议 ✅ 已缓解(3db216c):mcp-server 加 server instructions + 状态工具 report-only 描述,防止 LLM 把非 OK 状态当事故、主动给一堆排查建议

2. Phase 2:监控 + 纠错闭环(✅ 已实施 2026-08-12)

  • SSE 事件流(ADR-004 已实施):apiserver /xce/v1/events + EventBroker、schedulerclient WatchJobs()、mcp-server 4 高级工具。t1 集群验证:SSE 流推送 PEND→RUN→DONE、WatchJobs 捕获完整生命周期、4 工具全部 live 工作。
  • 高级工具:scheduler_wait_job、scheduler_analyze_failure、scheduler_suggest_resources、scheduler_estimate_wait_time(14 工具)
  • Agent 工作流已打通:submit → wait_job → 取日志 → analyze(详见设计文档 §5.3)

3. Phase 3 / Phase 4:后端适配器(未开始)

  • Phase 3:LSF adapter(CLI 解析优先,Python Sidecar 后续,估 +1 月)
  • Phase 4:Slurm(slurmrestd)+ K8s(client-go)(估 +1 月)

4. 推迟 / 未决

  • scheduler_modify 工具推迟——apiserver 当前无 modify 端点(control 仅 kill/stop/resume/checkpoint),需新增后端端点
  • 3 个未决决策:LLM 模型选型(Claude API/自建/混合)、多集群 URM 来源识别、air-gapped LLM 访问
  • PEND reason 分类体系(未完成,2026-08-13 调查+设计稿已出):见 docs/pend-reason-investigation-design.md。数据链路已通(bug-1513,ac6131d),但喂进去的 reason 只有 2 种——已实现阻挡点 8 处里仅 3 处产生 reason,limit 插件/队列/时间窗/fairshare 等 8 类 LSF 必有原因全部静默或桩。待统一决策:(a) code 策略——复用 3 code + 明细子码 vs 扩展 PREASON_* 到 ~20 个;(b) 接线优先级——建议 P0=修 main_reason + limit 插件 attach reason,P1=队列状态/时间窗/worker 过滤,P2=依赖/license/保留/exclusive/fairshare;(c) 是否补 LSF 风格的 bjobs -p 等价能力到 MCP 工具。

5. 设计层加固(文档已写、代码零实现)

  • Auto-pilot 模式:用户显式授权范围内的自主行为
  • AI 操作审计日志:每条操作记 [timestamp] [user] [action] [params] [confirmed?]
  • Golden test suite:同一自然语言输入 → 同一工具调用序列的回归测试

建议优先级(2026-08-13 更新)

  1. bug-1490 ✅ 已修复(c90e63e),写工具 E2E 通过。
  2. bug-1494 ✅ 已修复(bug-1510 + bug-1511,2026-08-11),作业全 PEND 解决。
  3. scheduler-agent Phase 2(SSE 事件流) ✅ 已实施并验证(2026-08-12)。
  4. msg-gap G-8/G-3/G-5——scheduler-controller 消息缺陷,小而明确,能立即修。
  5. component-failover-adoption(scheduler/worker/apiserver 重启后自动重连)——仍是最重要基础设施缺口;apiserver 的 rejoin 缺口已实测确认。
  6. scheduler-framework 重构——大规划,建议等前几项稳定后再动。
  7. scheduler-agent 下一步:Phase 3 LSF adapter(估 +1 月),或先跑通 agent 工作流真实试用 + 补齐 3 个未决决策(LLM 选型/多集群 URM/air-gapped)。