10 KiB
阶段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水位。循环调用3ABeginBatch(watermark);空批次结束。- Set批将batch items转为字符串字典;Delete批转为key列表。请求数据必须来自已持久化batch快照。
- HTTP 200后调用3A
ConfirmBatch,只有确认快照落盘成功才完成票据。 - HTTP失败后按
PlayerKVResult.MayHaveCommitted调用3AFailBatch;401/403同时标记认证失效。任何MayHaveCommitted=true都冻结为Unknown,不自动重试。 - 只有有正面证据“未进入传输”时可按false失败并允许以后重新Get;不要根据400/401自行推断未写。
- Flush汇总至少报告Confirmed/Superseded/Blocked/Unknown数量及最终错误类别;调用者取消等待不成为共享HTTP token。
3.4 原子准入、失效与Close
Owner内需要一个短临界区统一完成:检查closing/closed、登记实际操作、取得租约。操作退出必须finally归还。禁止“先检查状态,稍后登记”。
CloseAsync:
- 在同一准入门内原子置closing,禁止新操作;重复调用返回同一个关闭任务。
- 退出锁后取消owner token;取消回调可能同步执行,不能持锁Cancel。
- 结束尚未完成的被动票据等待;等待者本身不算必须drain的实际操作。
- 等待已登记的初始化/调度/磁盘操作全部退出,不持admission/state/dispatch锁等待。
- 最后依次释放协调器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必须按顺序更新自己的实施记录:
- 固定接口草图、锁顺序及文件边界;确认不需要改3A。
- 实现Coordinator纯调度和结果模型,先配HttpMessageHandler替身测试。
- 实现SessionOwner创建/归属/Close,补并发交错测试。
- 完整离线测试、原3A/阶段2测试回归、Unity编译。
- 生成最终源码hash、列明未执行项,停止开发并交还主会话审查。
不得自行进入3C、访问s101、接游戏入口、修改状态/TODO、打包、提交或发布。
6. 3B验收矩阵
至少覆盖:
- 创建:未认证、错误账号/API、Get 200空字典、Get401/403/协议/网络/取消、打开缓存Busy/RecoveryRequired;失败不留锁/transport。
- Cookie:两个owner各自独立Cookie/handler;捕获后调用方切session或Dispose,旧owner不借新Cookie;禁止自动重登。
- 串行:Set/Delete交错、批10、51+key、Flush水位、连续编辑时Flush可结束,最多一个HTTP在途。
- 多版本:v1在途产生v2;v1确认后v2保留;尚未发送v1被v2替换时v1票据Superseded。
- 票据:两票据同批,其中一个等待取消不影响HTTP/另一票据;取消Flush等待不撤销目标;重复等待得到一致事实。
- 故障:预发送取消、发出后取消、超时、网络、400/401/403/500、HTTP200后磁盘确认失败、active写前磁盘失败;逐项核对unknown、pending和票据。
- 换号/代际:101请求在途→失效→102 owner;101迟到200/401不改变102状态,不使用102 Cookie,不发布全局事件。同号新epoch同样隔离。
- Close:检查与登记交错、并发Update/Flush/Close、Cancel同步回调重入、重复Close、transport延迟/忽略取消、文件锁仅实际收尾后释放。
- 回归:KVContractTests 42、KVSyncTests 86保持通过;新增测试直接编译实际生产源码;Unity编译0错误,新文件无新增警告。
允许测试使用合成API和Cookie、任务目录缓存;不允许正式服写入或真实业务key。测试必须有确定超时,不能无限等待。
7. 实施AI交付格式
完成时只报告:
- 修改/新增文件及SHA256。
- 新增测试数量、分组、命令和退出码。
- 阶段2/3A回归及Unity编译结果。
- 独立说明哪些是合成传输证据,哪些尚未验收。
- 已知限制或任何偏离任务书的点。
主会话收到交付后将逐文件审查、复跑关键测试、检查工作区差异,并决定通过、要求返工或补裁决。实施AI不得自行宣布3B最终验收通过。