Files
ft/CodexOutput/upserver/项目审查补充-2026-09-21.md

59 lines
7.4 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.
# 项目审查补充:s101 迁移
日期:2026-09-21。基线 HEAD:f40a816cc,审查对象为当前未提交工作区。按《接手入口.md》继续审查,结合《开发状态.md》《后续实现方案.md》《审查记录.md》《开发日志.md》与最新最小登录收尾评审、验收记录判断现状。
本次仅更新文档,没有移动、迁出或修改业务代码,没有提交、推送、连接正式服或操作玩家数据。审查范围集中于迁移相关认证、HTTP、SignalR、俱乐部调用及现有测试,不代表全项目所有玩法审计。使用 unity-project-scout 核查项目基线:Unity 2022.3.62f2c1,URP 14.0.12、Addressables、HotUpdate 程序集;PlayFab SDK 和异步包仍在 manifest 中。
## 裁决与开发边界
**本批审查结论:有条件通过继续准备 A/B;完整退出安全与业务会话隔离暂不通过;C 存档切换、D SDK 删除仍不放行。**
最新最小登录收尾中的 HTTP 代际过滤、SignalR 首连预绑定、订阅释放和旧 RPC 结果过滤已存在,不重复列为未修复。以下三项是当前源码仍需处理的问题,其中 F1 为历史问题复核,F2/F3 为补充证据。
本文件只形成问题裁决和建议,不授权立即改代码。后续先完成具体方案的完整评审并记录文件边界,再实施:F1/F2 限于身份分类及相应 ClubService 调用者;F3 涉及 QuitAct、UserService/渠道 override 与 RT 生命周期,由同一集成人协调。不得全局替换 UserId、改变旧存档命名空间或直接复用 manager 实现 KV 写入。
## F1 / P1:俱乐部本人身份仍混用 PlayFab ID(已知,仍未修复)
- 证据:`Client/Assets/Scripts/Services/UserService.cs:452` 明确 `UserId = loginResult.PlayFabId`;`ClubService.cs:232,294,355,436,477,497,507,518,532,545,594` 的本人 `playerId` 仍读取 `userService.UserId`。`:311` 的 `internalIdToPlayerId` 也写入旧身份。
- 契约复核:相邻服务端本地源码 `LeaderboardAPI/Services/Club/ClubService.cs:176–177,600` 对 CreateClub/QuitClub 的 playerId 使用 `PlayerIdUtil.Parse`,并按该值查询玩家/会员。这是本地契约证据,不宣称与线上部署版本完全一致。
- 触发与影响:s101 登录成功后调用这些功能,旧 PlayFab 字符串可能不能按十进制解析;即使恰好全是数字,也不等于渠道身份,仍会查询错误的 ID。没有据此宣称线上已发生错误写入。
- 建议:先完成本人、目标玩家及缓存映射的身份清单;本人新 API 使用已认证 ApiPlayerId,未认证不发送;目标 ID 按来源转换,不能替换成本人 ID。保留旧 PF 存档身份。
- 验收要求:模拟本人/目标玩家区分、未认证阻断以及映射缓存;会员变更不得以正式账号写操作代替测试。
## F2 / P1:manager 丢弃旧响应后,上层仍会修改俱乐部状态
- 证据:`CustomServerMgr.SendAsync` 对过期响应、网络失败及 HTTP 失败返回 null。`ClubService.cs:298–320` 的 CreateClub 在 null/空响应时清空 `myClubInfo` 并发布状态变化;`:480–489` 的 QuitClub 完全不判断响应,直接退出聊天、清空俱乐部与点赞游标、显示提示并发布状态事件。两者均未像 GetSelfClub 一样检查请求所属 SessionVersion。
- 触发与影响:退出俱乐部请求断网/失败时,本地仍表现为已退出,而服务端可能未变更;若旧调用在会话变更后恢复,则 manager 返回 null 仍不能阻止调用者执行本地副作用。跨账号可见影响取决于服务实例是否复用,但同账号失败误报不依赖该条件。
- 建议:请求前固定会话版本,await 后先过滤失效会话;失败保留原状态,按实际业务响应确认成功后才清理。不能仅将 playerId 改为 ApiPlayerId 后便宣称 A 阶段完成。
- 验收要求:覆盖 CreateClub/QuitClub 的网络失败、HTTP 失败、业务失败和旧响应;断言不清空已知状态、不发成功事件。当前 GetSelfClub 已有版本和 null 保护,不能把它的通过扩大到所有 ClubService 方法。
## F3 / P1:退出等待 Hub 释放期间,账号仍然有效
- 证据:`Stages/QuitAct.cs:35–56` 在销毁 UI、重置配置后,先 await `rtService.ReleaseAsync()`;`userService.Logout()` 直到 `OnStarted` 的 `:70–73` 才执行。`UserService.cs:649–659` 的退出代际递增、HTTP 会话清理及 PF 凭据清除都发生在 Logout 内。RT ReleaseAsync 只立即使 RT 自身失效,然后等待生命周期锁和 Stop/Dispose。
- 触发与影响:当 `QuitStage.Logout=true` 且 Hub 关闭尚未完成时,退出流程已经开始,HTTP 会话版本及登录退出代际却仍旧有效。在途 HTTP 成功可继续返回,当前 401 仍可能触发重登,等待中的登录也未因“开始退出”而失效。已存在的代际保护要等 Logout 真正执行才生效。
- 证据边界:这是源码执行顺序确认的窗口;没有运行 Unity/真实 SDK 复现。现有 RT 测试通过 StopGate 明确覆盖了“ReleaseAsync 尚未完成”,但没有编译实际 QuitAct/UserService,不能证明此窗口安全。
- 建议:专项评审退出入口的顺序:当本次确实要注销时,在第一个网络 await 前使身份和登录任务失效,再可等待地释放连接、清理场景;保留无需注销的退出路径语义,并处理 SessionChanged 与 ReleaseAsync 的协同及重复调用。不是简单删掉 await,也不直接移动代码后跳过评审。
- 验收要求:阻塞 Hub Stop,让旧 HTTP 200/401、API 登录及渠道 SDK 回调分别到达;确认不再更新状态、不重登、不返回登录完成,并验证释放异常时仍能完成必要清理。
## 本次实际验证与限制
本会话前段已实际执行以下离线命令,均退出 0;用户要求继续审查后未重复运行或增加测试代码:
```powershell
$env:DOTNET_CLI_HOME='C:/projects/ft/CodexOutput/dotnet-home'
$env:APPDATA='C:/projects/ft/CodexOutput/dotnet-appdata'
dotnet run --project CodexOutput/upserver/MinimalLoginTests/MinimalLoginTests.csproj --verbosity quiet
dotnet run --project CodexOutput/upserver/RealtimeTests/RealtimeTests.csproj --verbosity quiet
```
- MinimalLoginTests:31 项通过;编译实际 S101AccountSession、CustomServerMgr,未编译实际 UserService/AggUserService/ClubService/QuitAct。
- RealtimeTests:三组输出通过;编译实际 RTService,Hub、事件及引擎环境为替身。将 State 从 Reconnecting 改回 Connected 不等于真实网络自动重连。
- `git diff --check`:退出 0,仅有行尾转换提示。
- 本次未执行活动回归生成器、2079 源码编译、Unity 导入/场景、真实 SDK、正式服联调或 KV 写读删。这些既有验收记录仍为历史证据。
## 文档一致性与下一步
《开发状态.md》顶部已注明最小登录收尾完成,但历史区及《后续实现方案.md》《TODO.md》仍保留“首连/旧401待修复”等旧文字。接手时按最新收尾复审和本补充判断:底层已修复,上层调用者及退出起点仍有缺口;不能重复修复旧问题,也不能据此勾选全游戏隔离通过。
下一批先评审 F1/F2 的身份调用清单与失败语义,再单独评审 F3 退出顺序。B 的生产 Cookie/HttpClient 所有权及失效设计仍需具体化;本批没有检查或放行新的 KV 实现。审查建议的测试尚未实施,不计入通过。