Skip to content

feat(worker,cli): 同名 serve 跨机租约/互斥,重复执行不再零护栏(#99 跨机那半)#310

Merged
leeguooooo merged 1 commit into
mainfrom
feat/serve-cross-machine-lease-99
Jul 11, 2026
Merged

feat(worker,cli): 同名 serve 跨机租约/互斥,重复执行不再零护栏(#99 跨机那半)#310
leeguooooo merged 1 commit into
mainfrom
feat/serve-cross-machine-lease-99

Conversation

@leeguooooo

Copy link
Copy Markdown
Owner

做什么(#99,[P2][design],跨机那半)

同名 serve 多进程无租约/互斥 → 重复执行。同机那半已由 11b08c4 解决(本地单实例锁);本 PR 补跨机:不同机器上两个 serve 同名,原本都唤醒、都跑同一 @、重复劳动。

实现(服务端租约)

  • 服务端租约:serve 挂载时 serve_lease claim,DO 的 reconcileServeLease最小连接序号者持租,回 serve_lease{held} 帧告知各连接是否持租。心跳/断连(onClose / scanPresence 陈旧连接)触发改选——持租者/候选断连,下一条 standby 顶上(补发 held=true)。
  • serve 端:非持租者不跑 runner(standby 待命),只有持租者响应 @;持租者死(连接断/心跳停)→ standby 自动顶上;原持租者回来重新竞选。去重:只在 held 变化时补发帧。
  • 保留同机锁(11b08c4)不变,这是其上的跨机层。

门禁(对 origin HEAD rebase 到最新 main 后亲验)

🤖 opus agent 实现(服务端租约+standby 顶替+改选)、收尾截断我接管(审+rebase+复验)。

#99 有两半。同机那半(#237, commit 11b08c4)用本地 pid 单实例锁挡住同一台机器
再挂第二个 serve。这半补跨机器:工位机 + 家里机各跑一个 serve,服务端广播把每条 @
发给同名所有连接 → 两台都跑完整 runner、双份回帖、git push 类副作用执行两遍,唯一
线索是 who 里不起眼的 x2 sessions。本地 pid 锁挡不住跨机,必须服务端租约。

服务端 serve 租约(worker/src/do.ts):
- 每条 serve 连接挂上后发 {type:"serve_lease", op:"claim"} 声明自己是 runner。
- DO 在同名活候选里选 claim 序号最小的那条持租,回 serve_lease{held} 告诉每条连接
  是否持租——只在 held 变化时补发(去重)。序号取自单调 meta 计数器,首次 claim 定死。
- 持租者断连(onClose)/ 心跳超时(scanPresence 60s 扫描,即 TTL/heartbeat)→ 重选,
  存活候选里"次早"顶上、补发 held=true(takeover)。
- 软租约:原持租者重连拿到更大序号,不抢回当前 standby 的租约(return baton cleanly)。
- /presence 暴露 serve_standbys(候选数-1):who/web 一眼看出"重复 serve 但已被租约
  互斥、只有 1 台在跑",而非只能靠 connection_count x2 猜。

客户端遵从(cli/src/commands/serve.ts):
- 挂上/重连即 claim。hasLease 默认 true —— 老服务端不认租约、从不下发 serve_lease,
  客户端保持旧行为,不回归。
- 收到 held=false 转 standby:被 @ 也不跑 runner(qualifies 拦住),但消息仍进历史、
  游标照推进(与 #180 暂停接待同路径);held=true 恢复响应。跨进程互斥点在服务端。

同机锁(#237)原样保留,本改动是其上的跨机层。

TDD:worker 4 例(选举/takeover/软租约/standby 暴露)、cli 5 例(standby 不跑/持租
跑/takeover/老服务端不回归/发 claim)。变异验证:去掉 held 判定 → 两台都跑(红);
去掉客户端 hasLease 门 → standby 也跑(红)。

Claude-Session: https://claude.ai/code/session_01FS3jLbZK3AqVXgkhRcEEQg
@leeguooooo leeguooooo merged commit 2027ddc into main Jul 11, 2026
17 checks passed
@leeguooooo leeguooooo deleted the feat/serve-cross-machine-lease-99 branch July 11, 2026 12:16
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.

1 participant