feat(worker,cli): 同名 serve 跨机租约/互斥,重复执行不再零护栏(#99 跨机那半)#310
Merged
Conversation
#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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
做什么(#99,[P2][design],跨机那半)
同名 serve 多进程无租约/互斥 → 重复执行。同机那半已由 11b08c4 解决(本地单实例锁);本 PR 补跨机:不同机器上两个 serve 同名,原本都唤醒、都跑同一 @、重复劳动。
实现(服务端租约)
serve_lease claim,DO 的reconcileServeLease选最小连接序号者持租,回serve_lease{held}帧告知各连接是否持租。心跳/断连(onClose / scanPresence 陈旧连接)触发改选——持租者/候选断连,下一条 standby 顶上(补发 held=true)。门禁(对 origin HEAD rebase 到最新 main 后亲验)
reconcileServeLease让所有候选都 held(互斥失效)→ 唯一持租测试红。复绿。🤖 opus agent 实现(服务端租约+standby 顶替+改选)、收尾截断我接管(审+rebase+复验)。