fix(desktop): release isLoadingMore lock on invalidated initial history backfill - #3398
Conversation
…ry backfill When ensureInitialMessages backfill is invalidated by an epoch change (reloadMessages, purge, etc.), the old generation's early return left isLoadingMore permanently true, blocking all subsequent pagination. Release the shared pagination lock in retryInvalidatedInitialHistoryFetchIfNeeded so it is freed regardless of whether a retry occurs. Also release it in the .catch() error path to prevent lock leaks on fetch failure. Regression test confirms isLoadingMore is released after epoch invalidation. Signed-off-by: Battleplus <3559424769@qq.com>
|
| Filename | Overview |
|---|---|
| apps/desktop/src/renderer/lib/makerChatStore.ts | 分页锁释放增加 token 所有权保护,并补齐当前首拉失败时的锁清理;原先报告的旧请求清除新锁问题在当前 HEAD 已解决。 |
| apps/desktop/src/renderer/tests/makerChatStoreActiveView.test.ts | 新增 initial backfill 被 reload 引起的 epoch 变化作废后释放分页锁的回归覆盖。 |
Reviews (2): Last reviewed commit: "fix(desktop): gate isLoadingMore release..." | Re-trigger Greptile
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6a10910fda
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Signed-off-by: Battleplus <3559424769@qq.com>
|
Fixed both P1 threads: gated isLoadingMore release on fetch token ownership. The issue: retryInvalidatedInitialHistoryFetchIfNeeded unconditionally cleared isLoadingMore BEFORE checking ownsFetch. When a stale callback from a superseded fetch arrived after reloadMessages had already started a replacement backfill (which set isLoadingMore = true), the stale callback cleared the replacement's lock, allowing loadOlderMessages to race its background backfill. The fix: moved the ownsFetch check BEFORE the lock release. A stale callback from a superseded fetch (where _historyFetchToken no longer matches) now skips the lock release entirely, preserving the lock held by the newer replacement backfill. |
|
@Battleplus 👋 这个 PR 还有 1 条 review conversation 没 resolve(apps/desktop/src/renderer/lib/makerChatStore.ts),auto-review 因此暂时跳过、没法继续审查 / 合并。 如果你已经按评论改完或回应了,请到对应 thread 上点 Resolve conversation;全部 resolve 后,下一轮 auto-review 会自动重新审查这个 PR。 |
|
Reply to both review threads: Both P1 threads (greptile: stale request clears new lock + chatgpt-codex-connector: check fetch ownership before clearing) are addressed by the same fix. Root cause: retryInvalidatedInitialHistoryFetchIfNeeded cleared isLoadingMore BEFORE checking ownsFetch. A stale callback from a superseded fetch could clear the lock that a newer replacement backfill was holding. Fix: moved ownsFetch check BEFORE the lock release. Stale callbacks now skip the lock release entirely. The .catch() path already deletes the token before clearing, so it is not affected by this race. |
|
命中 UI 路径但 description 未附界面效果证据。建议补充改动后效果:截图/录屏,或改动后界面的 HTML 页面(```html 代码块、.html 附件或在线预览链接),便于确认界面符合 DESIGN.md。 |
|
This thread has been addressed. The Specifically, the The |
MagicLizi
left a comment
There was a problem hiding this comment.
审查未通过(P1×1)。
apps/desktop/src/renderer/lib/makerChatStore.ts:9933—retryInvalidatedInitialHistoryFetchIfNeeded在_historyFetchToken仍匹配时无条件清掉共享的isLoadingMore。同文件loadOlderMessages(约 11201–11209,#676)的不变量是:代际作废的在途请求不得碰这把锁,因为更新的翻页/跳转可能已经重新持锁。_historyFetchToken只在reloadMessages里被替换;删除/drop/trim 等路径会 bump_messagesEpoch并自己放锁,但留下 fetch token。于是:首拉持锁 → 删除放锁 → 用户滚动重新持锁 → 过期首拉回调ownsFetch仍为 true → 把别人的锁清掉。新测试走的是reloadMessages(会删 token),测不到这条路径。
请改成:这里不要清 isLoadingMore;锁只由重置路径自己释放,或仅在本代际仍持有分页锁时释放。补一条不走 reloadMessages、而是 epoch bump + 后续 loadOlderMessages 持锁的回归测试。
这些问题已在当前 head 的后续 commit 中修复(格式门/安全门已通过),自动 dismiss 旧的 CHANGES_REQUESTED 以解除合并阻塞。
MagicLizi
left a comment
There was a problem hiding this comment.
Code review passed (standard): isLoadingMore is released only by the owning history-fetch generation, and failed initial backfill also clears the pagination lock. No P0/P1.
|
翻页锁这次拆得很干净:过期的 initial backfill 不再误放掉新一代请求的 |
这次改了什么
摘要
Fixes #3377.
ensureInitialMessages取得共享分页锁isLoadingMore = true后开始异步 backfill。当 epoch 变化(reloadMessages / purge / rewind 等)导致旧请求被作废时,retryInvalidatedInitialHistoryFetchIfNeeded和.catch()错误路径都没有释放isLoadingMore,导致锁永久生效:spinner 永久显示、loadOlderMessages被 gate、用户无法继续翻页。修复:在
retryInvalidatedInitialHistoryFetchIfNeeded开头释放分页锁(无论是否重试,ensureInitialMessages会重新获取);在.catch()错误路径也释放锁。变更类型
fix缺陷修复范围
isLoadingMorelock release inretryInvalidatedInitialHistoryFetchIfNeededand.catch()error pathUI 变化
怎么验证的
cd apps/desktop && npx vitest run src/renderer/__tests__/makerChatStoreActiveView.test.ts— 35/35 passed (含新增回归测试)cd apps/desktop && npx vitest run src/renderer/__tests__/makerChatStoreJumpBackfill.test.ts— 全部通过releases isLoadingMore when initial backfill is invalidated by epoch change风险
修改
retryInvalidatedInitialHistoryFetchIfNeeded的锁释放时机。已验证:释放后若发生重试,ensureInitialMessages会重新获取锁;若不重试,锁正确释放。不会引入新的竞态。