fix(desktop): recover Runtime Host reads after reconnect - #3280
Conversation
Astro-Han
left a comment
There was a problem hiding this comment.
Thanks — separating "the database is healthy" from "the recovery path never rebound these reads" is the right diagnosis, and making app:info reconnectable is clearly correct. Reviewed exact head 2f89bcde025db8127dd89f1916e5bd47bd620b7b.
My concern is with how the transcript fix is expressed rather than with the intent. The guard was removed rather than narrowed, which leaves the invariant the new comment asserts unowned by any code, and the new test asserts that the stale request runs, not that it returns the right slice. Details inline, along with a note on the new logging.
No CI checks are currently reported for this head.
Review disclosure: this review was prepared with Claude Code, which read the diff at this head, traced generation through the observer and the preload transcript contract, and checked the surrounding reset path. The reproductions are code reading, not execution. The human contributor reviewed it before posting.
There was a problem hiding this comment.
Requesting changes on the current head. The app:info reconnectable-read change and the diagnosis that durable transcript sequence is not a Desktop replica generation both look sound. There is one blocking recovery gap inline: the new Host-epoch fence is never advanced in the preload handle after open() returns, so a real Host replacement turns all later range reads into permanent failures until the whole handle is recreated. Please make the range identity follow reset batches (or explicitly reopen the handle) and cover a post-open Host-epoch change.
Scope note, non-blocking: the candidate-exit/reconnect logging is useful but orthogonal to the read repair and substantially widens this PR. If it stays here, please keep reconnect errors generalized/redacted and isolate embedder-provided exit sinks so diagnostics cannot throw through the child-process event listener.
Review performed against fc7a9890.
- narrow the transcript range guard to the Session and host epoch, dropping generation from the range request contract so reads keep working across replica replacement and stale Hosts reject instead of reading a different slice - route candidate-exit diagnostics through a caller-provided onExit sink instead of console in the launcher library; Desktop manager owns the sink and candidate-entry logs the generalized lifecycle error message
The range request closure captured the open-time host epoch forever, so after a reset installed a replacement Host every subsequent range request sent the stale epoch and the Main-process guard rejected it. Track a mutable generation+hostEpoch identity alongside the handle: initialized from the open result, adopted from accepted reset batches, and used by every range request. Requests already dispatched with the old epoch still fail closed on the guard.
The rebase onto upstream main pulled in workflow updates; keeping the fork branch free of workflow changes so this PR does not touch .github/workflows.
e32f6a7 to
9f7a41a
Compare
Summary
app:infoa reconnectable read so project metadata queries survive connection lossRoot cause and behavior change
The Runtime Host database was healthy. The visible task-read failures came from an incomplete recovery path after the Host connection was lost: some reads remained bound to the dead connection, while transcript navigation rejected requests solely because the replacement replica had a newer generation.
After this change, eligible reads wait for the replacement connection, and durable transcript sequence requests continue against the current replica. The added diagnostics also make future Host exits and reconnect failures observable instead of leaving only downstream
connection_losterrors.Validation
npm --workspace @maka/runtime-host run buildnpm --workspace @maka/desktop run build:maingit diff --checkKnown local-only result: the owned-candidate suite passed 5/6; its prompt-exit timing test exceeded the 2-second election deadline on this Windows environment and was terminated by the test harness. The changed launcher code only observes the existing exit event and does not alter shutdown control flow.
中文说明
本次问题不是
runtime.sqlite损坏,而是 Runtime Host 断线后的恢复链路不完整:部分读取仍然发往旧连接,聊天记录请求也会因为后台换代而直接报错。修改后,可重试的读取会等待新连接;旧代聊天记录请求会交给当前副本实际执行。同时补充了重连失败、子进程退出码/信号和顶层生命周期异常日志,方便后续定位真正的退出原因。