数据持久化

06/285 浏览
这两个问题很可能是因果关系
投资数据没持久化
    ↓
刷新重进 → Store 加载出来的数据是空的/旧的
    ↓
PostWallNoteToServer() 计算的 profitCents = 0 或上次的旧值
    ↓
wall_profit 在 serverCloud 中始终是 0 或空
    ↓
GetRankList("wall_profit") 返回的要么是 0 要么干脆没有记录
    ↓
便签墙上显示 "+0元" 或者根本没有便签
更严重的情况:如果连 wall_profitSetInt 都没成功写入 serverCloud,那 GetRankList 查询结果为空 → 便签墙完全没有数据可显示。
horizontal linehorizontal line

验证链路

让我追踪完整的数据持久化链路:
环节时机是否可靠
用户添加交易点击"保存"Store 内存修改
MarkDirty保存后标记应该有
SyncToCloud只在 Stop() 中 WASM 刷新不触发
serverCloud 写入UserDataProxy → 服务端如果 Sync 没调用就没机会写
重新加载刷新后 LoadFromCloud读到的是旧数据(因为没写入过)
PostWallNoteToServer登录后用 Store 数据计算基于旧/空数据计算 → 便签错误
核心断裂点SyncToCloud 几乎不被调用(只有 Stop),所以数据永远留在内存里,刷新就丢。
horizontal linehorizontal line

所以根因是同一个

数据不持久化 → 便签墙无数据
不是两个独立 bug,是一个 bug 的两个表现
  1. 表现 A:刷新后持仓/交易记录消失
  2. 表现 B:便签墙空白(因为 wall_profit 从没被正确写入)
horizontal linehorizontal line

修复方向(一个修复解决两个问题)

在 HandleUpdate 中加定时自动保存
lua复制
lua
local autoSaveTimer = 0 local AUTO_SAVE_INTERVAL = 15 -- 每15秒 -- HandleUpdate 中: if isLoggedIn and Store.IsDirty() then autoSaveTimer = autoSaveTimer + dt if autoSaveTimer >= AUTO_SAVE_INTERVAL then Store.SyncToCloud() autoSaveTimer = 0 end end
这样:
  • 用户修改数据 → 15秒内自动同步到 serverCloud
  • 刷新重进 → LoadFromCloud 读到最新数据
  • PostWallNoteToServer 用正确的 profit 计算 → 便签墙正确
要现在修复吗?
06-28 18:04
[图片:暂不支持黏贴,请手动导入]
嗒啦啦忙完啦,接下来想做什么?
消耗53积分|剩余1501通用积分
评价一下嗒啦啦的工作
嗒啦啦陷入沉思中...
好的发现。既然数据持久化没问题(刷新后还在),那便签不显示是独立的问题
让我重新分析便签不显示的原因:
horizontal linehorizontal line

排除持久化问题后,便签不显示的可能原因

原因 1:时序问题(最可能)

登录页渲染(立即)→ 便签区域为空
    ↓(等待 1~10 秒)
服务器连接成功 → ServerReady
    ↓
WallClient 发送 CLIENT_READY
    ↓
服务器返回 WALL_SYNC_ALL(便签数据)
    ↓
Login.RefreshWallWithData(notes) → 更新 UI
如果用户在服务器返回数据之前就点了"进入系统",便签渲染的回调就没机会触发了。
horizontal linehorizontal line

原因 2:wall_profit 从未被写入 serverCloud

在多人模式下,PostWallNoteToServer 只是把便签发给了 WallServer 的共享墙内存(uid=0 公共池)。
serverCloud:SetInt(uid, "wall_profit", profitCents) 这一步可能从未执行
原来设计是用 clientCloud:SetInt("wall_profit", profitCents)(排行榜写入),但多人模式 clientCloud 为 nil,所以:
操作standalone 模式multiplayer 模式
写 wall_profit 到排行榜 clientCloud:SetInt 没有对应代码
便签发到共享墙 无服务端 WallServer
排行榜查询能看到(从未写入 iscore)
这就解释了为什么管理员面板显示 “+0元” —— wall_profit 作为 iscore 从没被写入过。
horizontal linehorizontal line

原因 3:你说的昵称问题

你改了昵称为 “3H”,但便签系统显示的名字取决于:
  • PostWallNoteToServer(WallClient, Login.GetNickname()) 中的 nickname 参数
  • 如果 Login.GetNickname() 返回的是旧值(“coco” 或 “1118015608”),便签上不会显示 “3H”
但这不会导致便签不显示,只会导致显示错误的名字。
horizontal linehorizontal line

真正的 Bug 是什么

最可能的组合:
  1. 服务器连接慢 → WALL_SYNC_ALL 返回时,可能已经过了登录页
  2. 共享墙为空 → 因为 PostWallNoteToServer 是在登录成功后才调用,第一次看登录页时服务器里还没有任何便签
  3. 刷新进入时:服务器如果重启了(persistent_world 不保证永久运行),内存中的便签会丢失,需要从 serverCloud 重新加载
循环死锁
登录页需要便签 → 便签在登录成功后才写入 → 只有下次进入才能看到
    ↓
但如果服务器重启了 → 内存清空 → 又需要从 serverCloud 加载
    ↓
如果 serverCloud 中 wall_profit/wall_msg 没写入 → 加载出来也是空
horizontal linehorizontal line

修复方向

  1. 服务端登录时写 wall_profit iscoreserverCloud:SetInt(uid, "wall_profit", profitCents) 在用户数据保存时同步写入
  2. WallServer 持久化 — 确保共享墙数据在服务器重启后能恢复
  3. 本地缓存便签 — 上次看到的便签数据保存本地,下次立即渲染(不等服务器)
  4. 昵称同步 — PostWallNoteToServer 使用用户实际设置的昵称
4
2