You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3.0 KiB
3.0 KiB
Config to MySQL - 验证报告
- Change: config-to-mysql
- 日期: 2026-07-04
- 验证人: AI Agent
- 分支: feature/20260704/config-to-mysql
验证项
| # | 检查项 | 结果 | 证据 |
|---|---|---|---|
| 1 | tasks.md 全部完成 | ✅ | 所有 18 个子任务已勾选 |
| 2 | 实现符合 Design Doc | ✅ | 单表 app_config、统一 ConfigStore、JSON fallback |
| 3 | 实现符合 proposal | ✅ | symbols + ai 配置迁移到 MySQL,保留 JSON fallback |
| 4 | 测试通过 | ✅ | python -m pytest tests/ 110 passed, 2 xfailed |
| 5 | 新增测试覆盖核心场景 | ✅ | tests/test_config_store.py 8 个用例覆盖命中/未命中/降级/迁移 |
| 6 | 无硬编码密钥 | ✅ | 代码审查未发现 |
| 7 | 无 SQL 注入风险 | ✅ | 使用 SQLAlchemy ORM 参数化查询 |
代码审查
审查方式: general_purpose_task 子代理审查
已修复问题
| 级别 | 问题 | 修复方式 |
|---|---|---|
| CRITICAL | MySQL 写入失败时 JSON 已更新但 MySQL 仍为旧值 | set_config 改为先写 MySQL,成功后再写 JSON;失败返回 False 并保留 JSON 旧值 |
| IMPORTANT | JSON 文件直接覆盖写入 | 使用临时文件 + replace 原子写入 |
| IMPORTANT | JSON 损坏时回填 MySQL 默认值 | 新增 _load_json_from_file,损坏时返回 None,get_config 使用 fallback 但不回填 |
| IMPORTANT | _save_to_mysql 返回 False 时未处理 |
set_config 检查 _save_to_mysql 返回值 |
| MINOR | 多处未使用导入/变量 | 已清理 |
接受的风险
| 级别 | 问题 | 接受原因 |
|---|---|---|
| IMPORTANT | AI 配置中的 api_key 以明文存入 MySQL JSON 字段 |
超出本次 change 范围;JSON 文件原本也是明文存储,风险未扩大;建议后续单独 change 增加加密或敏感字段隔离 |
分支处理
- 本地合并到主分支
- 推送并创建 PR
- 保持分支
- 丢弃工作
结论
重新验证发现的问题
问题: 应用启动时配置迁移被跳过,MySQL app_config 表为空。
根因: app.mysql_database.MySQLSessionLocal 在 init_mysql() 执行前被 app.config_store 模块通过 from app.mysql_database import MySQLSessionLocal 导入,捕获了初始值 None。后续 init_mysql() 重新赋值模块变量后,app.config_store 中的名称仍指向 None,导致 ConfigStore 无法获取有效的 MySQL session,迁移被跳过。
修复:
app/config_store.py: 改为通过sys.modules动态读取app.mysql_database.MySQLSessionLocal,始终获取最新值app/config_migration.py: 使用store.session_maker检查 MySQL session 是否初始化
修复验证:
- 清理 app_config 表后启动应用,日志显示成功迁移 symbols 和 ai 配置
- 数据库查询确认
symbols配置包含 38 个品种(与 JSON 文件一致) - 全部测试套件 110 passed, 2 xfailed
结论
验证通过。实现符合设计,测试覆盖核心场景,代码审查和手动验证发现的问题均已修复。