Files
ft/CodexOutput/upserver/B3BatchMigration/M2/M2-先移植后优化完整方案-修订1-待独立审查.md
Liubing\LB 6813da149a feat(upserver): 保存M2客户端KV迁移至本人统计写检查点
保存独立KV用户服务、固定会话存档与原业务接线,以及C3d资料缓存和C3e本人统计写。
保留原PF/AGG路线、业务公式和时序;榜单读取、好友资料、公告、匹配及首场景闸仍待完成。

验证:ServiceHost两条件各33组646断言;Unity CLI Loop编译0错误269警告。
包含相关方案、评审裁决、测试及状态文档。未操作服务器、正式账号或打包。
2026-09-30 19:19:05 +08:00

11 KiB
Raw Blame History

M2:PlayFabMgr 存档能力迁至 KVMgr,先移植后优化(修订1,待独立审查)

日期:2026-09-29。状态:方案送审稿,不批准生产代码。本方案承接用户确认的流程图和“先完成移植、再据证据优化”的顺序。实施前须由原 ZCode 审查会话完整审查;主会话复算受审 hash、逐条裁决并写明批准白名单。后续业务批仍需各自完整调用矩阵和方案审查;本稿的总体路线通过不等于授权修改全部 81 个文件。

1. 目标、当前事实和路线选择

目标是在保留 PlayFabMgr.cs 历史文件的前提下,让需要保留的业务存档入口和正式运行调用最终由 KVMgr/KV 承接,旧管理器的运行调用、组件自动执行与 PF 存档发送归零;直接 PF SDK 外围依赖另列清理,最后再考虑移包。正式地址固定 http://s101.local:18080/。使用 Unity CLI Loop,不用 UnitySkills,暂不打包。

已关闭的 B02 仅将 ReadKV/WriteKV/FlushKVAsync/WaitForKVTicketAsync 四个固定 handle 入口从旧类等价迁入 Core/KVMgr.cs,并非旧管理器的全量替代。现行扫描为 224 个语法候选/81 文件:164 个 UpdateUserDataValue、50 个 GetLocalData、2 个 SyncDataImmidiate、1 个 CompareDatas 及 7 个内部/SDK 候选。它不是完成率或可机械替换的行数;逐项依据为 M2-当前调用矩阵-待核证.json。

历史核证:9 月 15 日仓库树 f40a816cc 中的旧管理器没有 Guard;9 月 28 日 upserver 提交 0eb43b2b4 才加入 Guard 实现和旧方法检查,B02 原样搬迁带 Guard 的四个 KV 入口。它是迁移新增的保护,不是旧 PF 业务语义。迁移期先保留当前 Guard 类、入口检查、计数与错误返回,完成后单独判断是否可以删减。

路线 裁定理由
选用:KV 能力承接+按业务动作迁调用 每个旧入口有明确新合同;业务公式与 UI 时序仅做必要适配,错误可定位。
直接把整份 PlayFabMgr 复制改名成 KVMgr 新类仍依赖 PF SDK、PlayerPrefs 合档和旧定时队列;不能实现 KV 后端替代,还需第二次迁移。
全局文本替换类名,最后统一补保护 旧 string/null、void、bool 无法表达 KV 读错、写拒绝和远端 Unknown,扣费/领奖可能误判。

2. 职责和调用数据流

flowchart LR
  B[玩法/业务 Service] -->|原账号固定 handle、key、值| K[KVMgr:读、写、Flush、原票据观察]
  L[登录/加载/退出 Service] -->|成功 Apply 后发布;撤销时清除| B
  L -->|进入/释放受控加载门| G[当前 Guard]
  K -->|现行拒绝检查暂保留| G
  K --> H[GameSessionHandle/Owner/缓存/同步]
  H --> S[s101 KV]
  P[PlayFabMgr 历史文件] -.待所有运行引用清零.-> X[停止组件自动执行]

KVMgr 只提供存档入口,不登录、决定账号、枚举场景组件、调用 UserService 或管理第二套缓存。调用方持有登录会话发布的原 handle;关闭或同账号新 epoch 后原 handle 不得重新指向新 Owner。PlayerKVAccountLease 是账号网络租约,不可冒充存档 handle。

现行 PlayerKVGameLoadCoordinator.LoadAsync 是验证路径:它在 Apply 成功后仍持有 Guard,LoadedForValidation 也要求 Guard 存在;四个 KVMgr 方法在此期间均会被拒绝。因此不得把 LoadKVForValidationAsync 简单改名并开放给正式玩法。Editor 限定玩法已经验证另一时序:Guard 覆盖 Apply,成功后释放,随后发布固定 handle。正式路径需要借鉴这个时序,但不能直接沿用 Editor 许可、测试 bridge 或 PF 登录回退。这一项是可写玩法的必需迁移适配,不是 Guard 类优化。独立审查须重点裁决以下最小方案:保留验证路径原行为;为正式加载增加明确模式/入口,成功 Prepare→Decode→31模块Apply 且通知完成、身份/epoch 有效后,释放该次 Guard,再一次性发布同一原 handle;失败只 Revoke/Close,不发布。不得让“Guard 仍持有但写调用绕过它”成为修补办法。正式句柄的受控出口只能由当前 PlayerKVLoginContext/协调器按身份、epoch、关闭状态给出,不能用全局单例查询或泄漏历史 Prepare 结果。若这套分流必须大量复制现有验证代码,审查应判定需要重做本节,不得在实施中临场扩写。

3. 旧成员逐项去向与必要差异

旧成员/行为 本次迁移验收口径
GetLocalData(key): string/null KVMgr.ReadKV(originalHandle,key);分别处理存在值、合法缺键和读取失败。调用点不得把失败伪装成空档或默认数值。
UpdateUserDataValue(key,value,remoteStore): void KVMgr.WriteKV(originalHandle,...);本地 Accepted 与远端 Confirmed 分开。无消费的状态标记可按已审 B01 合同处理;发奖/扣费必须归入所属业务动作。
SyncDataImmidiate(key,value): Task<bool> 同一原 handle 的 Write→Flush→该次原票据观察;现有两处分别归钓鱼鱼饵和转盘券消费批。Unknown 不当成功或自动重试。
CompareDatas PF 远端与 PlayerPrefs 时间戳合档只用于旧 PF/受控历史迁移;正常 KV 登录使用现有 Prepare→Decode→Apply。保留旧路径直至登录来源政策审定,不复制 PF 合档算法到 KVMgr。
InitBuffer/SyncData/UpdateFaild/40秒PF循环 对照现有 KV Owner 的缓存/同步行为和正式运行触发。先保留旧 PF 路径;停用前核对定时、暂停、退出是否有等效触发与失败可见性。不得照搬第二套 PF 队列。
Awake/OnApplicationPause/Quit/OnDestroy/Instance 先核现有触发链;在全部存档调用及退出接线验证后停止 SubBoostrap 创建旧组件。是否需要最小生命周期接线以真实缺口为准,不预先新增通用适配框架。
Editor Start/StopKVGameplayLoopSync 继续受原许可和测试宿主限制;正式运行不可引用这些方法。旧组件停用前需保证测试入口有单独去向。

4. 连续实施检查点与边界

CP0 审查与基线。 冻结本稿、224项矩阵和本批源码 hash;原 ZCode 审查总体路线、Guard 时序、正式 handle 出口和首批白名单。主会话逐条裁决后写出确切批准范围。B02 44 项冻结交付和 B01 关闭证据只读复用;不清理当前用户未提交的场景、字体与其他源码修改。

CP1 正式会话前置。 在批准文件中建立 Player 构建可用的 31 模块绑定/快照、正式身份/加载入口和原 handle 交接;受控验证工厂仍只限验证。Guard 只在加载副作用敏感窗口阻断,正式成功发布前退出;失败/撤销清除绑定并等待既有 Close 屏障。不得更改 Guard 类和 KVMgr 四入口方法体。此阶段先用合成 transport、旧/新 epoch 和 Apply 失败验证,不切默认 KV、不运行真实账号。

CP2 管理器对外能力与首批接线。 复用四入口,针对旧三类对外存档调用明确调用方结果适配;优先复用 B01 已关闭的通知/俱乐部状态作为代表链,不重写其业务计算。每一组记录旧 key、最早内存变化、原 handle 来源、失败停止点、旧回调行为、对应测试。若需要 KVMgr 新方法,必须是确实无法由四入口表达的存档能力且先经白名单审查;不能增加旧 PF 同签名的假成功转发。

CP3 业务域连续迁移。 按核心进度及奖励、活动商业及延迟回调、身份及加载边界三个较大业务域推进,不按 224 行逐项审批。每域形成可审的调用/上游/源文件白名单及验收矩阵后一次完整审查,再连续实施并在检查点记日志。消费与发奖链同一业务动作验收;数值公式、随机展开和 UI 顺序无证据不改。原 PF 分支保持可用直到对应域完成,不能同一动作混用两个后端写同一档。

CP4 旧管理器停止运行。 核对语法调用、别名/反射/Prefab/UnityEvent、组件创建、测试入口、定时和生命周期;在正式 KV 组合验证与账号/历史数据政策通过前,不停用旧组件或全局切默认。调用归零以后,旧 PlayFabMgr.cs 保留为历史文件,另处理它及外围的 PF SDK 编译依赖,再考虑移包。

CP5 验收后优化。 独立评估迁移时新增 Guard 是否还需要全局静态 owner、现有计数和当前目录位置。只有发现具体冗余/层级/并发问题并完成单独方案评审,才删除、缩小或移动 Guard/KVMgr;不把优化混入 CP1–4 的行为迁移补丁。

5. 首批源文件候选与明确排除

首批待审候选仅限以下职责所在文件,最终以独立审查和主会话白名单为准:Core/KVMgr.cs(原则上只核对,不改四方法)、Services/PlayerData/PlayerKVLoginContext.cs(受控原 handle 出口)、Services/PlayerData/PlayerKVGameLoadCoordinator.cs(正式/验证时序)、Services/PlayerData/PlayerKVControlledLoadCapability.cs(正式工厂与验证工厂隔离)、Services/PlayerData/PlayerKVGameplayBindings.cs(Player 构建 31 模块绑定可用性)、Services/UserService.KVLoad.cs 与 Services/UserService.cs(正式登录发布、撤销和初始接线),以及 B01 原八文件中确有正式接线需要的最小改动。SubBoostrap.cs 只在停用旧组件检查点有证据且方案审查后纳入,不在首批先改。测试可在 CodexOutput/upserver/B3BatchMigration/M2Tests/ 独立宿主和固定 Unity Editor 验证入口进行,禁止复制一套生产存档算法。

本稿尚未批准这些候选文件编码。CP1 精确签名、生产工厂配置来源、B01 首批需要修改的确切行、全部失败分支和源码白名单必须由独立审查裁决为充分,主会话随后形成批准版;若不充分,修订本稿再审。后续 81 文件不因本稿通过而自动获批。

6. 验收矩阵与停止条件

编号 必须证明的行为
V01 Guard 覆盖 Prepare/Decode/31模块 Apply 副作用窗口;Apply 失败或通知失败不发布原 handle;正式成功后 Guard 已退出且固定 handle 可读写。验证路径原 Guard 语义保持。
V02 同账号新 epoch、跨账号重登、Logout/Close/取消后的旧 handle 读写与迟到回调均拒绝,不写入新 Owner;Close 失败不绕过屏障。
V03 存在值/空串/缺键/读失败四种情形不会合并;写拒绝、本地 Accepted、远端 Confirmed/Unknown 不冒充彼此。
V04 两处立即消费调用各按原票据确认,失败/Unknown 不重复扣费、不自动补发;多键部分保存问题仍按 T08 作为默认切换前置。
V05 B01 已读/提示状态、31模块加载、B02 四入口/Guard、登录与退出回归保持;编译含 Editor、SERVICE_HOST、Player 目标条件,Unity CLI Loop 0 新错误。
V06 默认切换前有账号政策、历史档、连续普通玩法、退出后重新登录恢复及旧 PF 引用归零报告;没有正式接口写入授权时只跑合成 transport。

任一白名单外修改、Guard 类/四入口检查语义变化、把 PF SDK 发送塞进 KVMgr、需要全局当前账号、无法证明正式 handle 的撤销、或业务动作新增扣费/奖励重试,立即停止该检查点并修订方案交审。合同内实现错误可在已批准边界内修复、记录首败与回归,不逐函数重复申请。每个检查点更新 开发日志.md、入口与 TODO。暂不访问真实 101/102 档,不打包。