2.0 KiB
2.0 KiB
拼图运行态 run_json 计时字段兼容修复 2026-04-29
背景
作品详情页点击“启动”时,Rust API 通过 SpacetimeDB start_puzzle_run procedure 拿到字符串化的 run_json,再在 spacetime-client 映射层反序列化为拼图运行态快照。
本次线上报错为:
puzzle run run_json 非法: missing field `started_at_ms`
说明主云 procedure 已成功返回快照,但返回的 JSON 仍可能是旧字段集,没有带上后续限时与排行榜迭代新增的计时字段。
根因
PuzzleRuntimeLevelSnapshot 在早期 PRD 中只包含关卡基础信息、棋盘和状态。后续版本新增:
started_at_mscleared_at_mselapsed_mstime_limit_msremaining_mspaused_accumulated_mspause_started_at_msfreeze_accumulated_msfreeze_started_at_msfreeze_until_msleaderboard_entries
其中部分字段已经有 serde(default),但 started_at_ms、cleared_at_ms、elapsed_ms、leaderboard_entries 仍按必填字段解析。只要主云旧模块或历史快照缺少这些字段,API facade 就会在映射层失败,导致详情页启动中断。
修复口径
本次只做后端兼容,不改表结构,不改前端表现:
module-puzzle的运行态快照新增字段统一允许缺省。- 旧 JSON 缺
started_at_ms时,用当前毫秒时间作为兼容起点,保证前端倒计时不会从0时间戳开始。 - 旧棋盘缺
all_tiles_resolved时按false处理。 - 旧 run / level 缺
leaderboard_entries时按空榜单处理。 spacetime-client增加回归测试,确保run_json缺新增计时字段仍能启动。
经验结论
procedure -> run_json/items_json -> client record 这类链路只要返回字符串化聚合快照,新增字段就必须默认具备向后兼容能力。平台入口级操作不应因为单个新增字段缺失直接 500;能安全补默认值的字段,应在服务端契约层统一兜底。