Files
ft/CodexOutput/upserver/B3BatchMigration/M2/M2-双提供方用户服务切换与KV独立实现约束-2026-09-29.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

53 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# M2:保留 PlayFab 并新增独立 KV 实现的双提供方切换约束
日期:2026-09-29。**用户最新裁决,覆盖此前“最终删除 `PlayFabUserService`”的错误记录**:原 PlayFab 路线必须保留;另写独立的 KV 路线;用一个明确的启动开关选择 PlayFab 或 KV。不得把“移植完成”解释为删除 `PlayFabUserService`、`PlayFabMgr` 或 PlayFab SDK。此文供开发 Agent 接手和编制完整方案,**不是当前批次扩大代码白名单的批准**。
## 全局简洁性规则在 M2 的应用
遵守项目根目录的 [`AGENTS.md`](../../../../AGENTS.md):在满足已确认功能、正确性和必要安全边界的前提下,抽象越简单明了越好。双提供方方案先比较“复用现有接口并做最小拆分”与新增层次的成本;每新增接口、适配器、管理器或状态,都要指出不可省的职责和实际调用者。不要为了看起来对称而复制 `PlayFabUserService`、额外包裹 `KVMgr` 或叠加第二套开关/Guard。确有安全或生命周期约束时应保留并说明,不能以简化为由删掉必要保护。
## 目标调用关系
```text
游戏业务 / 登录入口
↓ 提供方无关的用户与存档契约
启动时选择提供方(PlayFab 或 KV;一次会话内不热换)
├─ PlayFabUserService + PlayFabMgr → PlayFab Client SDK(保留、可启用)
└─ 独立 KV 用户服务 + KV 存档入口 → KV 会话 / 业务 API(新增)
```
开关需有单一、可观察的选择结果,并在创建用户服务、存档实例及登录前冻结;不能在已登录或已有存档实例时改后端,不能在 KV 失败时静默回退 PlayFab。现有 `SaveBackend` / `PlayerKVRuntimeSelection` 可作为设计输入,最终开关语义和 DI 注册须经完整评审确定。PlayFab 路线和 KV 路线均须可分别启动与回归。
## 当前代码与应处理的边界
| 位置 | 当前事实 | 目标 |
|---|---|---|
| `Services/UserService.cs` | `PlayFabUserService : IUserService` 承载原 PlayFab 登录;`IUserService` 含 `EntityKey`、`playFabId` 等 PlayFab 语义。 | 保留原类与原功能;抽出真正共用的身份、资料、授权契约。PlayFab 专属能力留在 PlayFab 专属接口/实现,KV 不伪造 PlayFab ID 或 `EntityKey`。 |
| `Services/UserService.KVLoad.cs`、`UserService.KVGameplayLoop.cs` | KV 编排目前接入 `PlayFabUserService` partial,属于迁移过渡。 | 经评审后将 KV 登录、Coordinator、原 handle、生命周期与普通业务请求迁入**独立 KV 实现**或其组合组件;不继承 `PlayFabUserService`,不把旧类复制一份。清理旧类中迁移后闲置的 KV 分支,但保留其 PlayFab 路线。 |
| `Stages/LoginStage.cs`、`PFLoginAct.cs` | 当前 DI 注册 `PlayFabUserService`/AGG 子类,登录入口又读取具体旧类的 KV 状态。 | 按冻结开关注册相应实现,登录入口经中立结果/会话契约消费;去掉 KV 对旧具体类型的下转,保留 PlayFab 模式的合法依赖。 |
| `Core/PlayFabMgr.cs` 与 `Core/KVMgr.cs` | 前者旧存档缓存/同步直接调用 `PlayFabClientAPI`;后者通过 `PlayerKVGameSessionHandle` 操作 KV。 | 两条提供方路径并存;业务逐步改依赖中立存档入口或提供方适配层,PlayFab 模式仍可调用原同步能力,KV 模式只用原 KV handle,不启动旧 PF 定时同步。 |
| `PlayerKVGameplayBindings.cs` | 31 模块绑定仍要求 `PlayFabUserService`。 | 抽离 KV 加载接收/身份状态所需的窄契约,保持 Apply、Guard、epoch、失败回滚原合同;PlayFab 模式功能不回归。 |
| `AggUserService.cs` | AGG 当前继承 `PlayFabUserService`。 | 保留现有 PlayFab/AGG 通道;KV 是否覆盖 AGG 需另行评审,不能因新增 KV 服务自动改变渠道行为。 |
## 实施顺序与验收
1. 先按既有审查白名单收口当前 CP2B-T 批次。后续新增双提供方方案须完整评审,明确开关、契约拆分、DI、账号与业务玩家身份、31 模块、AGG、异常/退出/旧 epoch 处理、场景和 Prefab 绑定,再逐项裁决开发边界后编码。
2. 建立独立 KV 用户实现及其 KV 存档路径;保持 PlayFab 实现可运行。各批迁移业务调用时同时验证 PlayFab 与 KV 两侧的读写、身份、失败及退出行为,不以空实现或临时冻结冒充完成。
3. 最终通关前按[临时门控清单](M2-最终通关前临时门控与忽略路径清理清单-2026-09-29.md)解除开发期跳过路径,核两种开关模式的完整业务链、重启恢复及安全边界;只清理迁移后闲置的过渡实现,不删除仍供 PlayFab 模式使用的类、SDK、注册和资源。
4. `PlayerKV*` 命名按既有用户裁决,在整体移植完成后另批处理。`Core/KVMgr.cs → Services/PlayerData` 的物理层级反向依赖另行纠偏,不因双提供方方案自动认定已解决。
**验收标准**:一个启动开关可明确启用原 PlayFab 路线或独立 KV 路线;二者互不串用凭据、存档与运行时实例;PlayFab 旧功能回归通过,KV 全链通过,KV 不再依赖 `PlayFabUserService` 的具体类型或 PlayFab SDK,且迁移期保护门在最终通关前按清单销账。正式地址、101/102 当前准入和服务器代码边界遵守既有裁决。
## 项目结束前必须逐项确认的边界(当前均未验收)
以下项目必须由最终实现、调用图、双模式运行证据和审查裁决逐项销账;不能因本文已写下目标就标记通过。
- [ ] **PlayFab 路线保留**:开关选择 PlayFab 时,`PlayFabUserService` 仍负责其登录/资料,`PlayFabMgr` 仍负责旧存档缓存与同步,并直接使用 `PlayFabClientAPI`;其余 PlayFab SDK 调用按原功能保留。确认原渠道、场景、Prefab、DI 注册及代表性业务回归,而不是只证明能编译。
- [ ] **KV 路线独立**:开关选择 KV 时,使用独立的 KV 用户服务和基于原 `PlayerKVGameSessionHandle` 的 KV 存档路径;不得借 `PlayFabUserService` 实例、`PlayFabMgr` 活动实例或 PlayFab SDK 凭据完成 KV 业务。当前 KV partial 与旧类绑定应有经评审的抽离结果。
- [ ] **开关只有一处决策**:启动阶段明确选择并冻结提供方;用户服务、存档、账号会话、普通请求和场景入口得到一致选择。登录后不得热切换,也不得因 KV 错误静默落到 PlayFab;失败时保持可解释的错误和可恢复边界。
- [ ] **业务依赖可读**:业务层依赖中立且语义明确的用户/存档契约,提供方专属类型留在各自实现或适配层;核 `IUserService` 中的 `EntityKey`、`playFabId`、`UserId` 语义,`PFLoginAct` 的具体类型下转,以及 31 模块绑定。不能为了共用接口给 KV 伪造 PlayFab 身份。
- [ ] **抽象简洁性**:逐项说明最终保留的接口、适配器、管理器和状态各自的实际调用者与不可省职责;合并重复开关、重复状态和无消费者的包装层。用真实调用图确认业务流程能直接读懂,复杂性只来自已确认的功能或必要保护。
- [ ] **会话与写入隔离**:分别核两模式的登录、授权、读写、同步/票据、退出、暂停恢复、重启恢复、过期凭据和旧 epoch 回调;确认 KV 的 Guard/原 handle 租约与 PlayFab 的原同步路径不会交叉执行或串档。
- [ ] **渠道和临时路径清账**:明确 AGG 与其他渠道各自支持哪种提供方;按临时门控清单恢复为开发方便而冻结/忽略的功能。只清理无消费者的过渡 KV 分支与闲置实现,不能误删仍供 PlayFab 模式使用的代码和资源。
- [ ] **最终证据与裁决**:输出两种开关设置的真实最终调用流程图、覆盖上述项目的测试/运行证据和未覆盖范围;完成独立复核与主会话逐项裁决后,才可将双提供方边界标记为通过并结束项目。