发一次测试留言,却显示了2遍

05/041 浏览综合
现在完全清楚了。根因分析:
重复评论的完整流程:
用户点击"发送" → main.lua 第 1200 行:WallClient.PostComment(brick.id, commentInput, ...)
Client.lua PostComment 内部做了乐观更新到 Client.brickData[brickId].comments(这是 Client 模块自己的缓存)
main.lua 第 1201 行:table.insert(brick.comments, ...) — 又在本地地图 brick 对象上插入了一条(第1次本地插入)
Client.lua 发送 POST_COMMENT 到服务器
服务器 applyChange 把评论加入 brickCache_,然后 broadcastBrickUpdate 广播回所有客户端(包括发送者)
客户端 HandleWallBrickUpdate → onBrickUpdateCallback_ → mergeBrickData → 第 1577-1578 行:brick.comments = cloudData.comments
关键问题在于 第 5 步:服务器广播回了发送者自己。cloudData.comments 包含了服务端新增的那条评论。mergeBrickData 用 brick.comments = cloudData.comments 做整体替换。
但 cloudData 来自 Client.brickData[brickId](Client.lua 的乐观更新缓存),而这个缓存在步骤 2 中已经插入了一条。然后服务器广播回来的数据也包含这条评论。
等等,让我重新理一下。HandleWallBrickUpdate 收到的是服务端的 brickData(brickCache_),不是 Client.brickData。所以 cloudData 来自服务端。
流程是:
main.lua 本地 brick.comments 加了 1 条(现在有 N+1 条)
服务端 brickCache_ 也加了 1 条(现在也有 N+1 条,但可能之前已经有一条旧的同内容评论)
服务端广播回来,mergeBrickData 用 cloudData.comments(N+1 条)替换 brick.comments
如果之前只有 N 条,替换后还是 N+1 条,不会重复。
但如果这条砖块之前就在 brickCache_ 中有旧评论,且 mergeBrickData 在处理中出了问题呢?
等等,我再想想。注意 broadcastBrickUpdate 广播给所有连接,包括发送者自己。如果我们从时序上看:
本地立即 table.insert(brick.comments, newComment) — brick.comments 现在有 [旧…, 新]
服务端处理后广播回来,cloudData.comments = [旧…, 新]
brick.comments = cloudData.comments — 替换为 [旧…, 新]
这是正确的,不应该重复。
让我再仔细看看,是不是还存在第二次合并的路径,比如 rebuildFromCloud 或 SYNC_ALL 触发了第二次合并。或者可能问题在于 Client.brickData 的乐观更新和 BRICK_UPDATE 的交互。
1
7