[Bug] Git Log 加载更多报 Invalid Git history cursor:cursor 会话空闲 120 秒被回收且无自动恢复

Aperta
#1,652 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
25/100
Tipo di issue
Bug
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
git, rust, typescript
Ambito
backend, devtools

Direzione di ricerca

Start in rust/lithe-core/src/git/history.rs, where HISTORY_CURSOR_IDLE_TTL, the reaper and the git.historyPage cursor sessions live, then read the client handling in use-git-log-controller and getGitHistoryPage. Reproduce by idling past 120 seconds before loadMore, and confirm the Invalid Git history cursor error. Done means that loadMore recovers after idle expiry without leaving the panel in the failed state. The maintainers have not chosen between stateless tiered paging and an offset fallback, so agree on the approach first.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

review: medium
Platform / 平台

Windows

Area / 模块

Git

Lithe version / Lithe 版本

0.6.6(stable 安装包)

Priority / 优先级

P1 / 尽快处理:使用体验大幅下降,但通常仍可继续使用

OS and architecture / 操作系统与架构

Windows 11 Pro(build 26200),x64

Environment / 环境信息
  • Lithe 0.6.6 stable 安装包,普通用户权限运行
  • 项目:本地 Git 仓库(私有项目,路径以 <WORKSPACE> 代替),远端走 SSH
  • 事发时同期有一次 git fetch --prune -- origin 因 SSH 网络缓慢持续约 25 分钟未返回(fetch 本身与故障无因果,只是拉长了用户不滚动列表的时间窗口)
  • 最近一次发生:2026-11-02 13:28(本地时间)
Steps to reproduce / 复现步骤

以下步骤依据 0.6.6 源码时序推导,并有一次真实发生的控制台日志佐证(见"日志"字段);由于回收机制是确定性定时触发,预期为稳定复现,未逐条实测:

  1. 打开任意 Git 仓库项目,打开 Git Log 面板,首屏(50 条)加载成功
  2. 保持列表不做"滚动到底部"的操作超过 120 秒(实际场景:等一次慢速 fetch、切去别的窗口)
  3. 滚动到底部,触发自动加载更早提交
  4. Git 控制台出现 Invalid Git history cursor,列表停在已加载部分,之后滚动不再自动加载
Expected behavior / 预期行为
  • 滚动加载更多在任何空闲时长后都应继续可用;分页状态因空闲过期应对用户透明(自动丢弃游标并重载第一页/当前锚点),不应把整个面板置为失败态
  • 参考 IntelliJ 的成熟做法(intellij-community 源码):Git Log 分页不在服务端维持会话状态。滚动到底时按档位(CommitCountStage(5, 100, 2000, ALL))从 HEAD 重新拉取一次短命 git log --max-count=N(GitLogProvider.readFirstBlock),在客户端与已有数据按哈希合并(VcsLogRefresherImpl + VcsLogJoiner,连接失败则升档直至全量),因此不存在游标过期问题,也没有常驻 git 进程
  • Lithe Core 的 git.historyPage 已保留无状态的 offset 兼容路径(一次性 git log --skip=N,跑完即退),客户端迁移到档位式无状态分页可以复用现有契约
Actual behavior / 实际行为
  • 滚动加载更早提交时 Git 控制台出现一条空命令记录,错误为 Invalid Git history cursor,并标注"未收到已完成的命令记录";面板进入失败态,后续滚动不再自动加载
  • 根因(对照 0.6.6 源码,rust/lithe-core/src/git/history.rs):
    1. git.historyPage 的 cursor 实际绑定一个长驻 git log 子进程会话(流式 stdout + 读线程)。为防进程/线程泄漏,会话有三种回收:空闲 120 秒 TTL(HISTORY_CURSOR_IDLE_TTL,后台 reaper 每秒扫描)、并发会话上限 8 个按 LRU 驱逐(MAX_HISTORY_SESSIONS)、显式关闭
    2. 首屏加载后用户超过 120 秒未触发翻页,会话被 reaper 回收;下一次 loadMore 携带旧 cursor 请求,Core 返回 invalid_request: Invalid Git history cursor (git-history-cursor-N)
    3. 客户端两端的失败处理都没有恢复路径:Windows 端 getGitHistoryPage 失败被吞成 null,use-git-log-controller 将面板置为 failed 且游标已清空,loadMore 之后永远直接返回;macOS 端同样仅置 gitHistoryPageFailed = true
    4. 该失败请求没有真正启动过任何 git 子进程,Git 控制台 journal 为它生成了一条 arguments: [] 的"未确认"记录,显示为空命令 + "未收到已完成的命令记录",容易误导排查方向
  • 缓解条件:任何 git 变化事件(fetch/commit 等完成)会触发面板自动 refresh 而恢复;但慢速 fetch 挂起期间恰好没有任何事件,面板就停留在失败态,看起来像"查不到 Git 记录"
  • fetch 挂起/超时不是根因:任何让用户 2 分钟不滚动的情况都会触发;SSH post-quantum 警告只是 OpenSSH 的提示性输出,与本问题无关
  • 关联:#366(大项目 Git log 加载策略)催生了流式 cursor 分页方案,本问题可视为该方案引入的副作用;#788 已由 PR #882 修复(启动时争抢写租约,根因不同)
Logs or diagnostic output / 日志或诊断输出

Git 控制台记录(项目路径已替换为 <WORKSPACE>):

13:03:01.831: [<WORKSPACE>] git -c … --no-pager -c … fetch --progress --prune -- origin
** WARNING: connection is not using a post-quantum key exchange algorithm.
** This session may be vulnerable to "store now, decrypt later" attacks.
** The server may need to be upgraded. See https://openssh.com/pq.html
13:28:42.455: [<WORKSPACE>] git
Invalid Git history cursor
git-history-cursor-40
未收到已完成的命令记录

第二条记录即失败的加载更多请求(命令为空是因为它未启动任何 git 子进程)。

Screenshots or recordings / 截图或录屏

未提供(错误以控制台文本形式完整呈现,无界面截图需要补充时可再提供)

Checklist / 提交前检查
  • I searched existing issues for duplicates. / 我已搜索现有 Issue,确认没有重复报告。
  • I removed secrets and personal data from the report. / 我已从报告中移除敏感信息和个人数据。
Lingua principale
TypeScript
Stelle
1.8k
Fork
151
Merge medio
12h 6m
PR unite (30g)
365

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di 1lck/Lithe-IDEA

Tutte le issue di 1lck/Lithe-IDEA

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.