GFramework/ai-plan/public/data-repository-persistence/traces/data-repository-persistence-trace.md
GeWuYou 5353d5bd45 fix(game): 修复设置迁移缓存并发一致性
- 修复 SettingsModel 迁移注册与缓存重建的并发竞争

- 新增 SettingsModel 并发回归测试并更新 ai-plan 跟踪
2026-04-20 13:02:49 +08:00

8.5 KiB
Raw Blame History

Data Repository Persistence 追踪

2026-04-19

阶段legacy local-plan 迁移建档RP-001

  • 复核当前工作树后确认:根目录 local-plan/ 只剩一份 settings-persistence-serialization-tracking.md,它同时承担 todo 与 trace 角色
  • ai-plan 治理规则建立 ai-plan/public/data-repository-persistence/ 主题目录,并补齐:
    • todos/
    • traces/
    • archive/todos/
    • archive/traces/
  • 将旧混合文件拆分为主题内历史跟踪归档与基于同一材料整理的历史 traceactive 入口只保留当前恢复点、 活跃事实、风险与下一步
  • ai-plan/public/README.md 中建立 feat/data-repository-persistence -> data-repository-persistence 的 worktree 映射
  • 同步更新 ai-plan-governance 的 tracking / trace记录 legacy 单文件计划也已按新目录语义收口

Archive Context

  • 历史跟踪归档:
    • ai-plan/public/data-repository-persistence/archive/todos/data-repository-persistence-history-pre-rp001.md
  • 历史 trace 归档:
    • ai-plan/public/data-repository-persistence/archive/traces/data-repository-persistence-history-pre-rp001.md

下一步JsonSerializer 配置契约补充

  1. 后续继续该主题时,只从 ai-plan/public/data-repository-persistence/ 进入,不再恢复 local-plan/
  2. 若 active 入口再次积累多轮已完成且已验证阶段,继续按同一模式迁入该主题自己的 archive/

2026-04-20

阶段JsonSerializer 配置契约补充RP-001

  • 复核 GFramework.Game/Serializer/JsonSerializer.cs 后确认:当前实现直接复用传入的 JsonSerializerSettings,并通过 Settings / Converters 暴露活动配置对象
  • 复核 docs/zh-CN/game/serialization.md 后确认:现有 FAQ 把 JsonSerializer 写成“本身线程安全”,与当前可变配置契约不一致
  • 决定本轮只补齐契约说明而不改变运行时行为:
    • 在源码 XML docs 中说明 settings / converters 的生命周期与并发约束
    • 在定向单测中固定“序列化器暴露活动配置实例”的当前契约
    • docs/zh-CN/game/serialization.mddocs/zh-CN/game/index.mdGFramework.Game/README.md 中同步修正接入建议

下一步JsonSerializer 配置契约补充

  1. dotnet test GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release --filter "FullyQualifiedName~JsonSerializerTests" 已通过9/9
  2. 验证过程中出现的 analyzer warning 为仓库既有 warning未在本轮扩大
  3. 下一步回到 migration abstraction 与 codec / persistence pipeline 的后续评估

阶段迁移执行器统一收敛RP-001

  • SettingsModelDataRepositoryUnifiedSettingsDataRepositorySaveRepository<T> 的实现进行并排核对后确认:
    • DataRepositoryUnifiedSettingsDataRepository 不直接承担按版本号推进的迁移链
    • 实际重复点只在 SettingsModelSaveRepository<T> 的“版本迁移链执行与校验”逻辑
  • 决定不新增 public migration abstraction而是抽出 internal VersionedMigrationRunner
    • 统一前向注册校验
    • 统一缺链失败
    • 统一声明目标版本与实际结果版本一致性校验
    • 统一非递增 / 超目标版本防护
  • SettingsModel 本轮额外补强:
    • 拒绝同一设置类型同一 FromVersion 的重复注册
    • 以当前内存设置实例的 Version 作为目标运行时版本
    • 迁移失败时保持当前实例不被旧数据覆盖,并继续记录错误日志
  • SaveRepository<T> 改为复用同一个 internal runner但保留“加载成功后自动回写升级结果”的现有仓库语义
  • 同步更新 docs/zh-CN/game/setting.mddocs/zh-CN/game/data.md,补迁移链约束说明
  • 新增 / 更新测试:
    • SettingsModelTests:重复注册拒绝、不完整链路保持当前实例、缓存失效场景
    • PersistenceTests:迁移结果版本与声明版本不一致时显式失败

验证:迁移执行器统一收敛

  1. dotnet test GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release --filter "FullyQualifiedName~SettingsModelTests|FullyQualifiedName~PersistenceTests" 已通过20/20
  2. 过程中出现的 analyzer warning 来自仓库既有项,未在本轮扩大

下一步:迁移执行器统一收敛

  1. 进入 codec / persistence pipeline 边界评估
  2. 重点查看压缩、加密、元数据、备份是否仍然跨越 Serializer / Storage / Repository 多层分散

阶段PR #260 review follow-upRP-001

  • 复核当前 PR review 后确认两条未解决 inline 线程仍成立:
    • SaveRepository<T>.MigrateIfNeededAsync 在每一步迁移时都现查 _migrations,会让并发 RegisterMigration 把同一次加载暴露给变化中的迁移链
    • VersionedMigrationRunner.MigrateToTargetVersion 的 XML docs 仍缺少参数校验异常契约
  • 同步接受两条 outside-diff / nitpick 中仍然成立且低成本的 follow-up
    • SettingsModel.RegisterMigrationMigrateIfNeeded 需要补齐 XML 文档,和当前迁移约束保持一致
    • PersistenceTests 需要锁定“迁移失败后不会污染已持久化存档”的行为
  • 额外复核 docs/zh-CN/game/index.md 后确认:最低接入示例仍把 TypeNameHandling.Auto 用在用户可编辑的存档场景, 这与当前仓库安全约束不一致,因此一并改为默认安全配置并补充白名单说明
  • 本轮实现计划:
    • SaveRepository<T> 在加载前复制迁移表快照,再把 resolver 切换到快照读取
    • 新增并发回归测试,证明加载过程不会在迁移途中读到后续注册的链路
    • 补齐 VersionedMigrationRunner / SettingsModel XML docs
    • 更新 docs/zh-CN/game/index.md 示例与 active tracking
  • 实际落地结果:
    • SaveRepository<T> 已切换为在加载前复制 _migrations 快照,并在同一次迁移链执行中只读取快照
    • VersionedMigrationRunnerSettingsModel.RegisterMigrationSettingsModel.MigrateIfNeeded 已补齐缺失 XML docs
    • PersistenceTests 已新增“迁移失败不污染持久化数据”断言,以及并发注册下固定迁移快照的回归测试
    • docs/zh-CN/game/index.mdJsonSerializer 接入示例已改为 TypeNameHandling.None,并补充白名单 binder 说明

验证PR #260 review follow-up

  1. dotnet test GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release --filter "FullyQualifiedName~SettingsModelTests|FullyQualifiedName~PersistenceTests" -m:1 -nodeReuse:false 已通过21/21
  2. 本次验证未再出现本轮新增的 XML doc warning输出中的 analyzer warning 仍为仓库既有项

下一步PR #260 review follow-up

  1. 回到 codec / persistence pipeline 边界评估
  2. 继续判断压缩、加密、元数据与备份策略是否需要新的 dedicated pipeline abstraction

阶段SettingsModel 迁移缓存并发修复RP-001

  • 重新使用 $gframework-pr-review 复核 PR #260 后确认:此前遗漏了一条仍然 open 的 SettingsModel.cs major comment 问题点不是迁移执行本身,而是 _migrations_migrationCache 在并发注册和 cache miss 重建交错时,可能把旧快照写回缓存
  • 确认该 comment 来自 2026-04-20T04:23:09Z 的 CodeRabbit review run当前修复策略采用同一把私有锁串行化
    • RegisterMigration 中的 _migrations.TryAdd(...)_migrationCache.TryRemove(...)
    • MigrateIfNeeded 在 cache miss 时按类型重建 versionMap 并写回 _migrationCache
  • 同步补充源码注释与 XML remarks明确运行时注册与缓存重建共享同一并发语义
  • 计划新增 SettingsModelTests 回归测试,验证 cache rebuild 与运行时注册在同一把锁前排队后,后续初始化能看到新增迁移而不会留下 stale cache

验证SettingsModel 迁移缓存并发修复

  1. dotnet test GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release --filter "FullyQualifiedName~SettingsModelTests" -m:1 -nodeReuse:false 已通过5/5
  2. 本轮验证中未再出现 SettingsModel 新增的 nullable warning输出中的 analyzer warning 仍为仓库既有项加上新的 MA0158 建议,后者来自本轮新增对象锁

下一步SettingsModel 迁移缓存并发修复

  1. 若继续收口 analyzer 反馈,可评估是否将 _migrationMapLock 升级为 System.Threading.Lock,同时保留可验证的并发回归测试策略
  2. 否则恢复到 codec / persistence pipeline 边界评估