下载 App
【待解决】拍卖物品持久化
从你给的便签墙案例看,拍卖现在的 account_not_ready 很可能是同一类问题:异步数据域加载完成前,客户端已经允许用户发起业务操作;但这里还叠加了账户服务初始化时序问题。
这次只分析,不改代码。
一、拍卖当前实际链路
当前流程大致是:
text服务端 Start() ↓ 初始化 ServerAccountService ↓ 客户端 ServerReady ↓ 客户端请求: ├─ MARKET_LIST ├─ ACCOUNT_SNAPSHOT_GET └─ MARKET_PENDING_GET ↓ 服务端异步读取 zhuazhou_account_snapshot ↓ 账户加载完成 ↓ 客户端收到 ACCOUNT_SNAPSHOT_STATE ↓ 客户端 accountLoadStatus_ = found/migrated ↓ 允许上架
市场操作入口现在会检查:
text网络已连接 + ServerReady + 账户快照已加载
所以截图中的:
text上架失败: account_not_ready
说明不是商品配置、数量、价格或库存不足,而是服务端在处理 MARKET_PLACE 时:
luaaccountService:IsLoaded(userId) == false
对应位置:
- scripts/server_main.lua:147
- scripts/server_main.lua:599
- scripts/Network/ServerAccountService.lua:126
- scripts/Network/ServerMarket.lua:996
二、为什么会出现“看起来已经进交易行,但账户还没准备好”
和你分析便签墙的时序竞争类似,拍卖也有一个异步加载窗口:
text客户端页面已显示 ↓ 交易行可见 ↓ 账户快照仍在 serverCloud:Get() ↓ 用户点击上架 ↓ 服务端账户服务尚未 loaded ↓ account_not_ready
这里的关键区别是:
- 便签墙:服务端 WALL_CLIENT_READY 到早了,直接 return,导致同步永远丢失;
- 拍卖:市场操作到早了,服务端拒绝请求,客户端显示错误。
因此,当前拍卖不是“订单写入后刷新丢失”,而是订单压根还没有进入正式上架流程。
三、当前最重要的根因:账户服务初始化时序
账户服务原来在 server_main.lua 模块加载阶段创建:
lualocal accountService = ServerAccountService.New({ cloud = rawget(_G, "serverCloud"), cloudKey = ACCOUNT_SNAPSHOT_KEY, })
这发生在:
textserver_main.lua 被 require / 加载
而不是:
textserver_main.Start()
多人服务端运行时的 serverCloud 是运行环境注入的。模块加载阶段不能保证它已经准备完成,因此账户服务可能拿到:
luacloud = nil
随后:
luaAccountService:Load()
会走:
luaif not cloud or type(cloud.Get) ~= "function" then ... end
在没有旧主存档账户可迁移的情况下,就会变成:
text账户没有完成真正的云端加载 市场读取账户失败 MARKET_PLACE → account_not_ready
这就是截图错误最符合现象的解释。
已将初始化延迟到:
luaserver_main.Start()
让它在运行时注入完成后再读取:
luaserverCloud
这与便签墙案例中“等待异步资源完成后再发送数据”的修复原则一致。
四、账户加载和拍卖订单簿是两个独立加载窗口
当前市场实际有两个不同的数据域:
1. 全服订单簿
textUID = 1 zhuazhou_market_orders
负责:
- 在售卖单;
- 买单;
- 订单状态;
- 待交割记录。
它由 ServerMarket 自己加载:
textLoadMarketBookFromCloud()
并通过:
luamarketBookLoaded
控制是否允许订单操作。
2. 玩家账户
text玩家 UID zhuazhou_account_snapshot
负责:
- 钱;
- 锁钱;
- 仓储;
- 锁货;
- 已购商品;
- 交付幂等标记。
它由 ServerAccountService 加载:
textAccountService:Load()
并通过:
luaaccountService:IsLoaded(userId)
控制市场账户操作。
所以正确的市场操作前提其实是:
text订单簿 loaded + 玩家账户 loaded + 玩家会话有效 + Network ServerReady
目前截图中缺的是玩家账户这一项。
五、为什么这不是简单的“15 秒自动保存”问题
你提供的便签墙分析里,核心是:
text数据没有写入云端
而当前拍卖截图的表现是:
textaccount_not_ready
这两者要区分:
如果是订单已经上架,刷新后消失
才应该重点怀疑:
textMARKET_PLACE → marketOrders 内存 → TouchMarketBook → serverCloud:Set
中间是否断链。
但当前是上架瞬间失败
说明实际链路停在更前面:
textMARKET_PLACE → 账户校验 → accountService:IsLoaded == false → 直接拒绝
也就是说,当前这张截图还不能证明商品已进入订单簿,更不能归因于订单簿保存失败。
六、当前代码中仍存在的时序风险
即使初始化时序已经修复,仍有几个值得注意的加载竞争点。
1. 服务端向客户端发送 SERVER_READY 早于账户加载完成
服务端在 CLIENT_READY 中:
luaconnection:SendRemoteEvent(Shared.EVENTS.SERVER_READY, true)
随后才调用:
luaLoadAccountSnapshot(p)
因此客户端会先认为:
text服务端可用
但账户域实际上还在异步读取。
这本身不是数据错误,因为客户端现在还会检查账户状态;但 UI 层可能在账户未完成时已经允许用户打开交易行。
2. 客户端页面可以先显示交易行
交易行展示和账户加载不是同一个状态机。
结果可能是:
text交易行面板已经出现 账户状态仍为 pending 用户点击上架 客户端/服务端拒绝
这对应截图的用户体验。
3. 账户加载失败后虽然有重试,但原请求不会排队
现在账户失败或尚未加载时:
text上架请求 → account_not_ready
该请求会直接结束,不会等待账户加载完成后自动重试。
所以即使 0.5 秒后账户加载成功,刚才那次上架也不会自动恢复。
这和便签墙的 pendingClients 思路不同:
text便签墙:等待同步的客户端暂存 拍卖:等待账户的交易请求目前直接失败
七、结论
当前截图最可信的因果链是:
textserver_main 模块加载阶段过早创建 ServerAccountService ↓ serverCloud 尚未注入或不可用 ↓ 账户快照没有完成加载 ↓ accountService.IsLoaded(userId) == false ↓ MARKET_PLACE 被拒绝 ↓ 截图显示“上架失败: account_not_ready”
不是:
text上架成功 ↓ 订单簿没持久化 ↓ 刷新后消失
后者属于下一层问题,目前这张截图还没有进入那一步。
八、建议的下一步修复方向
如果继续修复,应该借鉴便签墙的“等待状态暂存”模式:
textServerReady ↓ 交易行可见 ↓ 账户加载中 ↓ UI 显示“账户同步中” ↓ ACCOUNT_SNAPSHOT_STATE(found/migrated) ↓ 开放上架、挂买、撤单
或者:
text用户点击上架 ↓ 账户未加载 ↓ 暂存本次 place 请求 ↓ 账户加载成功 ↓ 自动重新发送 MARKET_PLACE
更稳妥的产品行为是第一种:账户未加载时禁用交易操作,而不是让用户点击后得到 account_not_ready。
当前已经完成的修复只解决了最底层的初始化时序:
textServerAccountService 在 Start() 内初始化
但还没有实机确认账户云端读取成功。因此下一步实机日志应重点观察顺序:
text[Server] 服务端启动 [Server] 独立账户已加载 uid=... rev=... [市集] 独立账户已加载 status=found/migrated [Server] 市集上架卖单 [Server] 市集订单写入云端 [Server] 市集订单已持久化
如果日志中仍没有:
text独立账户已加载
那就不是拍卖商品配置问题,而是 serverCloud.Get 或账户加载回调仍未完成。






