db53de1a7ee729e74dc4c1e162765cc46a030ed3
review 判了两条 P2,都只动 W77 这一摊。 1) `loadIncrement` 里 `newest <= cursor` 那条同毫秒防线是死代码。服务端的 `after` 是 **严格** `>`(`list_after.go` 的 `ListAfter` 与 `devtools/fake-backend` 一致),返回的 每一行都 `createdAt > cursor`,那个分支永不触发。真实风险在别处:满页恰好把同一毫秒劈开 时,下一次 `after=newest` 只会回空页,旧代码把那次空页当成「追到了尾巴」⇒ 静默少给几条 且不回落。改成「拿过一整页之后紧跟的空页 ⇒ `complete = false`」:客户端分不出干净尾巴与 这个洞,就如实说没追完,把决定权交回调用方(未读面上是回落整表)。第一页就空仍算干净 尾巴(没有可少给的),不满一页仍算追到尾巴,翻满预算仍算没追完。 连带把测试改成真后端的形状:满页后空页那条的期望从 `complete = true` 改成 `false`;同 毫秒那条不再让假后端把同一批行回两次(严格 `>` 下后端给不出这种响应),改成「三条同毫秒、 页宽 2、第二页空」并断言第二次请求真的带 `after=500`;新增「第一页空页 ⇒ `complete = true`」把新逻辑的另一半钉住。KDoc 里「再翻也只会拿到同一批行」这类与契约矛盾的措辞一并 重写。 2) `applyIncrement` 的 `base + unseen` 在断线期间他端已读时会多计:`session_read` 帧永久 丢,`read_at` 又是账号级游标。代码行为不动,只把措辞限定清楚 ——「同源」的只是**过滤口径** (`count(created_at > read_at)`),基数仍是上次整表的旧值,跨端读会让它漂移,由下一次整表 刷新自愈。这是**已接受的边界**,KDoc 写明了,另加一条测试把它钉住 (`a read elsewhere while offline over-counts until the next whole table`),免得日后被 当成「已修好」。 不装「`readAt > from` ⇒ 回落整表」的保守闸:本端刚点开过该会话时 `readAt` 本来就被推到 「现在」、必然大于 `lastMessageAt`,那是最常见的一档;拿它当异常信号会让增量路径在正常 使用下持续回落整表,而真正的「他端已读」它一样抓不全(断线时帧就丢了)。抓不准的闸门不如 不装,理由写在 KDoc 里。 顺手把 `SessionItem.lastMessageAt` 与 `flushPendingIncrements` 里过时的注释改成新口径 (它现在同时是增量追尾的 `after` 游标)。 验证:`./gradlew.bat testDebugUnitTest assembleDebug` 全绿 —— 135 个 suite / 1691 条 (比上轮 +2)/ 0 失败 / 0 跳过,`assembleDebug` 打包成功。
Releases
5
Alpha_v0.1.0_4
Latest