Skip to content

bug: 手机端离线期间被桌面删除的历史消息,重连后仍留在窗口里 #1237

Description

@dashhuang

现象

手机端离线(退后台、断网、切端)期间,桌面侧删除了消息(/clear 清理某时刻之前的历史、rewind 回撤、单行删除),删除 push 收不到。重连后即使拉了最新页对账,窗口里早于本页最旧行的那些已删除消息仍会留在界面上,直到整窗替换(options.replaceMessages)或会话被回收。

复现(单测形态,实测输出)

窗口 = t10, t20, t30(一页权威页拉回,覆盖区间 = [t10, t30])
手机离线 → 桌面删掉 t10(删除 push 收不到)
重连最新页(满页,moreBeyondWindow: true)= t20, t30

实际: t10, t20, t30   ← t10 已被服务端删除,仍在窗口里
预期: t20, t30

同一形状在 origin/main#1210 之前)实测同样复现,所以这是既有缺口,不是 #1210 引入的回归。#1210 只是把它的触发条件从「缓存旧页与最新页有交集就整段保留」收窄到「旧行落在已验证覆盖区间内、且本页与该区间首尾相接」。

根因

setLatestMessageWindow 保留旧段的依据是「这段历史与本页连续」。#1210 加的事实自检能证伪一个方向——最新页在覆盖区间内带来了窗口没有的行 ⇒ 断言为假;但证伪不了反方向:窗口里有服务端已经删掉的行。满页时最新页到不了那些更早的行,页本身不构成证据。

修法方向

需要一条客户端能独立核对的「多行」信号,最现成的是总数对账session._count.messages 对上窗口里已加载的服务端行数(仓内 hasOlderMessagesAfterReopen 已经在用这个比较,可复用它的过滤口径)。窗口里的服务端行数 > 服务端总数 ⇒ 窗口里有已删除的行 ⇒ 作废覆盖区间、丢弃早于本页的旧段(甚至整窗重来)。

落地前要先核实的坑:

  • _count.messages 与「窗口里被算作服务端行」的口径是否严格一致(本地系统卡、临时流式行、tool 行的取舍);
  • 远程(SSH)会话与旧版被控端是否稳定给 count;不给时必须退化为「不对账」,不能当成 0;
  • 误判方向是清空用户正在看的历史,比现状(多显示几条已撤回的消息)更糟,所以需要偏保守的判据与专门的回归测试。

影响

用户可见但范围有限:只影响「离线期间桌面删过消息」+「重连时最新页是满页」这一组合,且被删的行必须早于本页最旧行。下一次整窗替换或重新打开会话(触发 replaceMessages 的路径)即恢复。

发现于 #1210 的 review(codex 的 thread,它给出的例子形状不复现——isOlderLoadedPage 还要求「旧行早于本页最旧行」——但指出的方向有上面这个真变体)。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions