Skip to content

fix(worker-budget): auto 预算按同机 bot 数均摊,避免多 daemon 各占整机额度#183

Open
baicaicc wants to merge 2 commits into
masterfrom
fix/worker-budget-multi-daemon
Open

fix(worker-budget): auto 预算按同机 bot 数均摊,避免多 daemon 各占整机额度#183
baicaicc wants to merge 2 commits into
masterfrom
fix/worker-budget-multi-daemon

Conversation

@baicaicc

Copy link
Copy Markdown
Collaborator

多 daemon 部署(一 bot 一进程)下,每个 daemon 都按整机 cpu/内存独立推导
maxLiveWorkers(如 56C/110G 机器 6 bot = 6×32=192),机器级上限被静默放大 N 倍,idle sweeper 形同虚设。改为机器预算 ÷ bots.json bot 数后再 clamp:

  • autoMaxLiveWorkers/resolveWorkerBudget 增加 daemonCount 参数(默认 1, 单 bot 行为不变)
  • bot-registry 新增 countConfiguredBots():mtime 缓存读共享 bots.json, CLI 一次性进程无注册表时回退 registry 大小
  • idle sweeper 与 worker-budget status/set 传入实际 bot 数;status 的 auto baseline 行展示 daemons 分母

@baicaicc baicaicc requested a review from deepcoldy as a code owner June 11, 2026 09:58
@deepcoldy

Copy link
Copy Markdown
Owner

是不是应该按会话数算总额上限比较好,平均分配可能又不太够了(毕竟有的bot用的多,有的用的少)
CleanShot 2026-06-11 at 23 35 40

@baicaicc

Copy link
Copy Markdown
Collaborator Author

想了下算总额也不合适,会出现多bot间强占,我把接入了报警,会出现很多的报警会话,我基本上也没有办法做到每个报警都主动关掉的情况;我去支持下单个bot允许自己自定义数量吧,这样如果不够,就单独加一下

@baicaicc

Copy link
Copy Markdown
Collaborator Author

已支持单个 bot 自定义 worker 预算(commit d5f1826),思路是「预设兜底 + 可选覆盖」:

  • bots.json 某个 bot 项里加 "worker": { "maxLiveWorkers": 30 }(也可配 idleSuspendMs)即可单独加额度,绕过均摊、不被其他 bot 强占;不配的 bot 行为完全不变。
  • 优先级:per-bot worker > 全局 config.json.worker > 均摊 auto 值。已配字段走 config 源(不参与均摊),未配字段逐字段回落到全局,再回落到均摊后的 auto baseline。
  • 关于「算总额会多 bot 强占」:确实如此(尤其接了报警后会有大量被动会话没法逐个关),所以没走总额制,改成每个 bot 自管、不够就单独加。
  • 简单版取舍:未配的 bot 仍按整机预算 ÷ bot 数均摊,从已配 bot 扣减,所以整机理论上可能略超——换取实现内聚 + 无强占。

改动:

  • bot-registry: BotConfig 新增可选 workerparseBotConfigsFromText 复用 global-config.readWorker 同口径校验;新增 ownBotWorkerConfig() 取本 daemon(一进程一 bot)的覆盖。
  • global-config: readWorker 导出以复用校验。
  • idle sweeper: { ...global.worker, ...ownBotWorkerConfig() } 字段级覆盖后传入 resolveWorkerBudgetworker-budget.ts 未改(已有 ?? 优先级链)。
  • 测试:bot-registry 解析 + ownBotWorkerConfig 共 6 例;sweeper per-bot 覆盖 3 例。build + tsc + 全部单测通过。

@deepcoldy deepcoldy left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review @ d5f1826(两 commit 一起看:均摊 + per-bot 覆盖)。

验证:build ✅ / tsc 0 错误 ✅ / 全量 unit 4223/4226(3 fail = master 既有基线:session-lifecycle-hooks 1 + transfer-session 2,与本 PR 无关)✅ / 与最新 origin/master 试合并干净(含 cli.ts)✅。

设计认可

  • 修的是真实问题:56C/110G × 6 bot 时整机 cap 被静默放大到 192,sweeper 形同虚设。
  • daemonCount 默认 1,单 bot / 既有调用行为零变化;测试里也专门钉住了 legacy 行为。
  • countConfiguredBots() 的 mtime 缓存与既有 brandLabelCache/oncallChatCache 同构,路径解析复用 loadedConfigPath ?? botsConfigDiskPath(),CLI 一次性进程也能工作。
  • per-bot 覆盖字段级 fall-through(per-bot > 全局 > auto 均摊)语义清晰,校验复用 readWorker 同口径;「已配 bot 不从均摊池扣减、整机可能略超」的取舍已在评论里明确披露,可接受。
  • daemon 侧唯一 sweeper 调用点(daemon.ts:3460)不传 opts.workerBudget,新路径全覆盖,无漏网调用点。

非阻塞建议(🟡)

  1. botmux worker-budget status 看不到 per-bot 覆盖:CLI 一次性进程 registry 为空,status 展示的预算 ≠ 配了 per-bot override 的 daemon 实际生效值,排查时可能误导。建议 status 顺手扫一遍 bots.json(数据源与 countConfiguredBots 同一份),列出带 worker 块的 bot 及其值。
  2. MIN_AUTO 下限(4)在 bot 数很大时会重新放大整机总额:30 bot × 4 = 120 仍可能超 110G 预算。比修前(30×32)好一个数量级,且 <4 的 worker 基本不可用,留意即可。
  3. countConfiguredBots 数的是 bots.json 原始数组长度,含 parse 时会被跳过的非法 entry——分母偏大→份额偏小,方向安全,无碍。

协调项:PR#184(idleSuspendMode per-bot)与本 PR 改动文件高度重叠(bot-registry/sweeper/worker-budget/cli/global-config 全撞),后合者需要 rebase;且两边都往 bots.json 引入 per-bot worker 形态配置,建议合并顺序定了之后让后者对齐本 PR 的 worker 块结构,避免出现两套 per-bot 入口。

zhubowen.cc added 2 commits June 13, 2026 18:34
多 daemon 部署(一 bot 一进程)下,每个 daemon 都按整机 cpu/内存独立推导
maxLiveWorkers(如 56C/110G 机器 6 bot = 6×32=192),机器级上限被静默放大
N 倍,idle sweeper 形同虚设。改为机器预算 ÷ bots.json bot 数后再 clamp:

- autoMaxLiveWorkers/resolveWorkerBudget 增加 daemonCount 参数(默认 1,
  单 bot 行为不变)
- bot-registry 新增 countConfiguredBots():mtime 缓存读共享 bots.json,
  CLI 一次性进程无注册表时回退 registry 大小
- idle sweeper 与 worker-budget status/set 传入实际 bot 数;status 的
  auto baseline 行展示 daemons 分母
均摊默认值对「有的 bot 用得多、有的用得少」不够灵活,而按会话总额算又会
出现多 bot 间强占。改为预设兜底 + 可选覆盖:每个 bot 可在 bots.json 自己的
项里配 worker { maxLiveWorkers / idleSuspendMs },按需单独加额度。

优先级:per-bot worker > 全局 config.json.worker > 均摊 auto 值。已配的
bot 用自己的值(走 config 源,不参与均摊、不被扣减);未配字段逐字段回落
到全局,再回落到均摊后的 auto baseline。简单版:未配 bot 仍按整机预算 ÷
bot 数均摊,不从已配 bot 扣减(整机理论可能略超,换取实现内聚 + 无强占)。

- bot-registry: BotConfig 新增可选 worker;parseBotConfigsFromText 复用
  global-config.readWorker 同口径校验解析;新增 ownBotWorkerConfig() 取
  本 daemon(一进程一 bot)的覆盖
- global-config: readWorker 导出以复用校验
- idle sweeper: { ...global.worker, ...ownBotWorkerConfig() } 字段级覆盖
  后传入 resolveWorkerBudget;worker-budget.ts 未改(已有 ?? 优先级链)
@deepcoldy deepcoldy force-pushed the fix/worker-budget-multi-daemon branch from d5f1826 to 85afddd Compare June 13, 2026 10:36

@deepcoldy deepcoldy left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

重新 review @ rebase 后 head 85afddd(已 rebase 到最新 origin/master 9b6cac2)。

rebase 验证:rebase 无冲突;rebase 后对 master 的 diff 与原版逐字节一致(未引入任何新增改动);master 自原 base(#179) 以来对本 PR 涉及的核心文件(bot-registry / worker-budget / idle-worker-sweeper / global-config)无语义改动,原子写 PR(a5f400b) 也未碰这几个文件,无隐性冲突。build ✅ / tsc 0 ✅ / 三个直接相关测试 bot-registry+idle-worker-sweeper+worker-budget 61/61 全过 ✅。mergeable=MERGEABLE。

结论维持上一轮 APPROVE,3 个 🟡 非阻塞建议不变。

合并顺序:本 PR(#183) 应先合。PR#184 的 base 指向本分支 fix/worker-budget-multi-daemon(stacked 在 #183 之上),不是 master——#184 依赖 #183 的均摊基线 + per-bot worker 块结构。建议:#183 先合入 master → #184 把 base 改回 master 并 rebase(届时 #183 的两个 commit 会被识别为已合并,#184 只剩 idleSuspendMode 自己的 diff)→ 解决与 master 冲突后再合。反过来先合 #184 不可行(其 base 不在 master 上)。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants