Repository navigation
[v2] 增加每项目 Node 驱动与按归属恢复 - #230
Conversation
独立只读审查(成员,非本运行 reviewer)审过 commit 已核对
非阻塞建议
装配时值得注意的两点(不是本 PR 要改的)
|
EricWvi
left a comment
There was a problem hiding this comment.
Requesting changes before merge (details in the linked run issue):
- After the Node transport dies,
p.fatalis reported asErrWorkspaceBusyinsession.go, and the deadprojectRuntimestays ind.projects, so every new session for that project fails as "workspace busy" until the process restarts. ReturnErrUnavailableand drop dead or failed projects from the map so the next session rebuilds them. - Failures are cached forever: project
initErr, failedcheckoutsentries andd.sessionsentries withprepareErrare never cleared, so one transient failure (plugin install, clone) disables that project, workspace or session permanently.control()/prepareCheckoutalso have no per-call timeout, so a single missing Node reply wedges the entry. - Please add a fake-IPC test layer for the driver path (
session/begin/submit/observe/End) that covers the recovery cases in 1 and 2. - (Can follow later) reclaim
sessions/agents/checkoutsentries.
Refs ora-space/circus#774
ObsisMc
left a comment
There was a problem hiding this comment.
复审 head 6348e75ab62bd4c9059818d8706b50a3342ce619(基线 main 8201254f)。
owner 上轮四项的核对
- 断线后返回
ErrUnavailable,不再报ErrWorkspaceBusy;Driver.project发现fatal后先close(supervisor 停止证明),成功才dropProject再重建,未确认时保留原条目。✅ initErr走 close + drop;clone 失败条目从checkouts删除;未派发 Start 的prepareErrsession 撤销 owner 预留并移出d.sessions;control有两分钟上限,单帧十秒,超时淘汰整个 incarnation,每次尝试用新 execution ID。✅- 八项 fake IPC 测试覆盖 Run/Append/End、持久化后 ACK、失败重试、断线停止证明、控制超时与迟到回复。✅
- 回收后置,README 已写明。✅
本地 Go 1.27.1(arm64):go vet 和 go test -race ./internal/agentruntime/ ./internal/node/ 通过;head 上的 server/frontend/e2e CI 也是绿的。
需要修改:断线后单靠 End 永远确认不了停止
已经派发过 Start 的 session,Node 断开后 End(sid) 只会 requestEnd(send 失败)再等 a.stopped;它从不对已死的项目调用 p.close。a.stopped 只有在另一个 Run 走到同一项目的 Driver.project、触发重建时才会被 closeResources 关掉。End 里的 p.close 分支只处理 initErr,不处理 fatal。
复现(基于本 PR 的 harness,stopOK 保持 true,只是断开传输):
done := startIPCRun(h, ctx, h.session("first", "workspace"), "turn", discardIPCEvent)
old := receiveIPC(t, h.created)
nextIPCCommand(t, old, "start_agent_session")
old.Close()
receiveIPC(t, done) // agent_transport_closed
h.driver.End(ctx, "first") // 连续三次都是 ErrStopUnconfirmed,old.stops == 0现有的 TestDriverIPCDisconnectRequiresStopProofBeforeRebuild 之所以能让 End("first") 最终通过,是靠中间那次 next session 的 Run 触发了重建。
影响(结合 #237 的消费方式):
- 工作流的下一个节点复用同一个 WorkspaceID 时,
executionruntime先agent.End(prior),失败就返回ErrStopUnconfirmed。同项目没有别的 Run 来触发重建,这个工作流就一直卡住,只能重启进程。这正是上轮第 1 项要消除的情况。 - 公开 End 或删除这条已断线的对话也会一直返回停止未确认,直到同项目有新会话进来。
建议:End 在 a.project.dead 已关闭(或 p.fatal)时,用调用方的 ctx 走 a.project.close(ctx),成功后 d.dropProject(a.project)。closeResources 已经会 markStopped 该项目下所有 agent,所以 End 再检查一次 a.stopped 就能返回 nil;close 失败时仍返回 ErrStopUnconfirmed,保留原条目,不破坏"先有停止证明再重建"的约束。另外把上面的复现补成回归测试。
其余没有发现阻塞问题。改完重新送审后我再复核。
ObsisMc
left a comment
There was a problem hiding this comment.
复审 head 594d25dbe25d46baaddead1748d84cb96c1b1835(基线 main 8201254f):上轮的阻塞问题已经解决。
- 项目 dead/fatal 时,
End用调用方 ctx 走p.close,由 supervisor 给出停止证明,成功后有条件地dropProject;停止失败仍返回ErrStopUnconfirmed,项目和 Workspace owner 都保留,后续End可以重试。closeGate和closed标志让它与Driver.project、Close并发时保持幂等。 - 我上轮的复现(
stopOK=true、只断开传输、不发起别的 Run)在新 head 上第一次End就返回 nil,supervisor 停止 1 次。 - 新增的两项回归覆盖了停止失败保留占用、单靠 End 重试成功、并发和幂等、同 Workspace 后继成功,以及等待别人关闭时遵守 ctx 截止。
- 本地 Go 1.27.1:
go vet通过;go test -race -count=10 ./internal/agentruntime/ ./internal/node/通过。head 上的 server/frontend/e2e CI 全绿。 - 改动文件都在
v2-server/下,都是交付物;描述写了「v2,不涉及 specs」和Refs ora-space/circus#774。
非阻塞:正常结束的 session、agent 和 checkout 条目还是保留到 Driver 关闭,README 已写明回收后置,由后续承接。
为已接收的项目会话增加独立 Agent Driver:每项目共享一个固定 Node,不同 Workspace 使用独立 checkout,首轮启动 Agent,后续轮次提交到原物理会话。历史与终态保存成功后才 ACK;End 等待有效停止确认,正常结束保留工作目录。
连接断开返回不可用,重建前先由 supervisor 确认旧进程树停止。断线会话可单独调用 End 完成旧项目停止和移除,无需另一个 Run 触发;停止未确认时保留目录占用,后续 End 可以重试。初始化、clone 和未派发 Start 的 session 准备失败不永久缓存;控制等待有截止,每次尝试使用新的 execution ID,超时淘汰当前 incarnation,隔离迟到回复。已经派发过的 Agent 不自动重放 prompt。关闭等待遵守调用方 context。
范围仅包含 Driver 与按归属恢复辅助;公共 Service、catalog、main 与页面装配由后续 PR 承接。本 PR 已同步 main
8201254f。验证:Go 1.27.1、真实 PostgreSQL 17.11 全包 gofmt/vet/race/build;十项新增 fake IPC 回归覆盖完整 Run/Append/End、持久化后 ACK、失败重试、断线停止证明、独立 End 恢复及同 Workspace 后继、控制超时与迟到回复、持久化失败不 ACK、并发关闭截止。独立 End 两项回归在旧实现失败,修复后相关回归 race 连跑十次通过。原生 WSL 的真实 Node/Agent fixture、长历史读回、取消及进程监督恢复均通过。公共装配候选复用本提交的同一驱动,真实 Service/Node 并发、重启读回及正式 CLI fixture-check 也已通过;其 Service 和入口不在本 PR 中。当前界面截图见关联运行。
v2,不涉及 specs。
Refs ora-space/circus#774