Files
ft/CodexOutput/upserver/阶段3B实施任务书-2026-09-22.md

136 lines
10 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.
# 阶段3B实施任务书:固定会话与串行同步
日期:2026-09-22。工作方式已由用户调整为:**主会话完成文档与最终审查;另一位AI负责实现和自测。** 本任务书是3B实施的唯一直接入口;完整技术依据仍为《阶段3缓存同步方案与评审-2026-09-22.md》及其独立方案审查。
## 1. 当前基线与目标
- 阶段2 `PlayerKVClient/PlayerKVModels` 已验收;正式地址固定 `http://s101.local:18080/`。
- 阶段3A `PlayerKVSyncModels/PlayerKVCacheStore/PlayerKVSyncState` 已验收:主测试86项、独立127断言、Unity编译0错误。
- 3B目标:把一个已认证且固定的 `S101AccountSession`、一个3A缓存命名空间和一个独立 `PlayerKVClient` 组合为单账号owner;所有Get恢复、Set、Delete和立即票据由单一调度器串行执行。
- 本批不接 `UserService`、`PlayFabMgr`、`CustomServerMgr`、玩法或全局容器;不访问正式服;不打包。
## 2. 所有权和允许改动
实施AI拥有:
- 新增 `Client/Assets/Scripts/Services/PlayerData/PlayerKVSessionOwner.cs` 及meta。
- 新增 `Client/Assets/Scripts/Services/PlayerData/PlayerKVSyncCoordinator.cs` 及meta。
- 新增 `CodexOutput/upserver/KVSyncCoordinatorTests/`,直接编译实际生产源码。
- 新增自己的实施日志 `CodexOutput/upserver/阶段3B实施记录-2026-09-22.md`。
- 可最小修改 `KVContractTests/KVContractTests.csproj` 与 `KVSyncTests/KVSyncTests.csproj`:将现有 `PlayerData/*.cs` 通配符改成各阶段实际需要的显式生产文件列表,使原42/86项回归命令在新增3B源码后仍能独立运行。不得修改两个目录的Program.cs、既有日志或测试语义。
默认禁止修改:
- 已验收的3A三个文件、阶段2两个文件、`S101AccountSession.cs`。
- `UserService`、`PlayFabMgr`、`CustomServerMgr`、`RTService`、玩法、配置、SDK、服务器代码及共享状态/TODO。
若实际实现证明3A缺少必要的窄接口,先在实施记录中写明:现象、不能在3B文件内安全解决的原因、最小签名和新增测试;暂停该处并通知主会话。不得先改3A再补说明。不得整批回退或整理工作区。
上述两个csproj例外仅用于固定回归编译边界:`KVContractTests`显式包含阶段2两个文件;`KVSyncTests`显式包含阶段2两个文件及3A三个文件。3B自有测试显式包含阶段2、3A、3B生产文件和 `S101AccountSession.cs`。禁止用额外MSBuild命令行注入来掩盖原项目本身已无法构建。
## 3. 必须形成的公开语义
具体类型名可小幅调整,但以下行为和信息不能丢失。
### 3.1 Owner创建
提供异步创建入口,输入至少包括:
- 已认证 `S101AccountSession`;创建时固定其 `ApiBaseUri`、规范化 `PlayerId` 和当前 `CookieContainer`。
- 缓存根目录、调用方不可变epoch、`Func<long,bool> isCurrent` 或等价归属检查。
- owner生命周期token。
创建时验证session非null、已认证、cookie非null、账号/API与缓存归属一致。使用捕获的CookieContainer创建owner专属 `HttpClientHandler`:`UseCookies=true`、`AllowAutoRedirect=false`,再创建owner专属HttpClient和已验收的PlayerKVClient。owner不Dispose认证session,不调用session.Login,不复用CustomServerMgr transport。
测试需要internal注入HttpMessageHandler/transport factory及可控调度钩子;生产公开入口不能允许任意运行期换Cookie或换账号。
创建流程:打开3A状态 → 获取操作租约 → `GetAsync(null, ownerToken)` → 再核对epoch/isCurrent/session归属 → 成功才 `Reconcile`。Get失败调用明确的read-failure路径;禁止将失败映射为 `{}`。创建失败必须收尾HttpClient和状态锁;返回结构化错误,不打印存档值、Cookie或响应正文。
### 3.2 Coordinator编辑与票据
提供:
- 远端Set编辑、localOnly编辑、Delete;返回3A写入结果及远端编辑票据。localOnly不创建远端票据。
- `FlushAsync`:捕获调用时水位,只处理该水位内版本;同一owner任何时刻最多一个变更HTTP在途。
- `WaitForTicketAsync(ticket, cancellationToken)`:取消只停止该等待者,不撤销已持久化pending、不取消共享Flush或同批其他票据。
票据至少固定owner实例/epoch、key和sequence。最终状态必须可区分:`Confirmed`、`Superseded`、`Blocked`、`Unknown`、`Cancelled`。不得用单个bool掩盖Unknown/Superseded。
- 精确sequence被HTTP成功且确认快照落盘:Confirmed。
- 尚未发送的旧sequence被同key新版本覆盖:Superseded。
- 进入unknown、冲突、认证失效、存储错误或owner关闭:按事实返回Unknown/Blocked/Cancelled,不能误报Confirmed。
- Wait调用者取消:该等待返回Cancelled,但查询同一票据的事实状态仍由协调器继续更新。
### 3.3 单通道调度
- 初始化Get、恢复Get、Set、Delete通过同一个调度入口串行;不得并行发两个KV变更请求。
- `FlushAsync`在开始时记录最大sequence水位。循环调用3A `BeginBatch(watermark)`;空批次结束。
- Set批将batch items转为字符串字典;Delete批转为key列表。请求数据必须来自已持久化batch快照。
- HTTP 200后调用3A `ConfirmBatch`,只有确认快照落盘成功才完成票据。
- HTTP失败后按 `PlayerKVResult.MayHaveCommitted` 调用3A `FailBatch`;401/403同时标记认证失效。任何MayHaveCommitted=true都冻结为Unknown,不自动重试。
- 只有有正面证据“未进入传输”时可按false失败并允许以后重新Get;不要根据400/401自行推断未写。
- Flush汇总至少报告Confirmed/Superseded/Blocked/Unknown数量及最终错误类别;调用者取消等待不成为共享HTTP token。
### 3.4 原子准入、失效与Close
Owner内需要一个短临界区统一完成:检查closing/closed、登记实际操作、取得租约。操作退出必须finally归还。禁止“先检查状态,稍后登记”。
`CloseAsync`:
1. 在同一准入门内原子置closing,禁止新操作;重复调用返回同一个关闭任务。
2. 退出锁后取消owner token;取消回调可能同步执行,不能持锁Cancel。
3. 结束尚未完成的被动票据等待;等待者本身不算必须drain的实际操作。
4. 等待已登记的初始化/调度/磁盘操作全部退出,不持admission/state/dispatch锁等待。
5. 最后依次释放协调器transport、3A state/file lease和owner资源,只执行一次。
Close不隐式Flush。已发送写被Close取消时仍可能提交,必须保留active/unknown证据;不能为了让新owner快速打开而强制释放锁。若transport不响应取消,关闭任务保持未完成,同命名空间新owner应Busy。
每个await前后检查owner epoch、`isCurrent(epoch)` 和lifetime。旧成功、旧401、迟到取消只能更新旧owner命名空间的可靠证据,不能向新owner发布事件、不能换用新Cookie重发、不能触发无归属全局重登。
## 4. 结果模型和日志要求
- 结果模型可放 `PlayerKVSyncCoordinator.cs`;不要为两个简单enum额外扩大生产文件。
- 不把 `PlayerKVError` 直接当完整同步状态;保留HTTP错误和缓存/票据状态两个层次。
- 日志/异常只允许账号是否匹配、epoch、数量、sequence、HTTP状态/错误类别;禁止存档值、完整请求JSON、Cookie和服务器正文。
- 任何异常都必须转换为结构化结果或使创建失败并可靠收尾;后台任务异常不得成为未观察异常。
## 5. 实施顺序和检查点
实施AI必须按顺序更新自己的实施记录:
1. 固定接口草图、锁顺序及文件边界;确认不需要改3A。
2. 实现Coordinator纯调度和结果模型,先配HttpMessageHandler替身测试。
3. 实现SessionOwner创建/归属/Close,补并发交错测试。
4. 完整离线测试、原3A/阶段2测试回归、Unity编译。
5. 生成最终源码hash、列明未执行项,停止开发并交还主会话审查。
不得自行进入3C、访问s101、接游戏入口、修改状态/TODO、打包、提交或发布。
## 6. 3B验收矩阵
至少覆盖:
1. 创建:未认证、错误账号/API、Get 200空字典、Get401/403/协议/网络/取消、打开缓存Busy/RecoveryRequired;失败不留锁/transport。
2. Cookie:两个owner各自独立Cookie/handler;捕获后调用方切session或Dispose,旧owner不借新Cookie;禁止自动重登。
3. 串行:Set/Delete交错、批10、51+key、Flush水位、连续编辑时Flush可结束,最多一个HTTP在途。
4. 多版本:v1在途产生v2;v1确认后v2保留;尚未发送v1被v2替换时v1票据Superseded。
5. 票据:两票据同批,其中一个等待取消不影响HTTP/另一票据;取消Flush等待不撤销目标;重复等待得到一致事实。
6. 故障:预发送取消、发出后取消、超时、网络、400/401/403/500、HTTP200后磁盘确认失败、active写前磁盘失败;逐项核对unknown、pending和票据。
7. 换号/代际:101请求在途→失效→102 owner;101迟到200/401不改变102状态,不使用102 Cookie,不发布全局事件。同号新epoch同样隔离。
8. Close:检查与登记交错、并发Update/Flush/Close、Cancel同步回调重入、重复Close、transport延迟/忽略取消、文件锁仅实际收尾后释放。
9. 回归:KVContractTests 42、KVSyncTests 86保持通过;新增测试直接编译实际生产源码;Unity编译0错误,新文件无新增警告。
允许测试使用合成API和Cookie、任务目录缓存;不允许正式服写入或真实业务key。测试必须有确定超时,不能无限等待。
## 7. 实施AI交付格式
完成时只报告:
- 修改/新增文件及SHA256。
- 新增测试数量、分组、命令和退出码。
- 阶段2/3A回归及Unity编译结果。
- 独立说明哪些是合成传输证据,哪些尚未验收。
- 已知限制或任何偏离任务书的点。
主会话收到交付后将逐文件审查、复跑关键测试、检查工作区差异,并决定通过、要求返工或补裁决。实施AI不得自行宣布3B最终验收通过。