---
change: config-to-mysql
design-doc: docs/superpowers/specs/2026-07-04-config-to-mysql-design.md
base-ref: 4956086
archived-with: config-to-mysql
---

# Config to MySQL - 实施计划

> 基于 [Design Doc](docs/superpowers/specs/2026-07-04-config-to-mysql-design.md) 拆分的可执行任务。
> 目标：将 `symbols_config.json` 和 `ai_config.json` 迁移到 MySQL，保留 JSON 文件作为 fallback。

---

## 任务总览

| # | 任务 | 依赖 |
|---|------|------|
| T1 | 新增 AppConfig 模型和 ConfigStore | - |
| T2 | 创建 config_migration.py 迁移脚本 | T1 |
| T3 | 在 main.py lifespan 中集成 | T1, T2 |
| T4 | 修改配置 API | T1 |
| T5 | 修改业务使用方 | T1 |
| T6 | 编写测试用例 | T1-T5 |

---

## T1: 新增 AppConfig 模型和 ConfigStore

**文件**:
- `app/models.py`
- `app/config_store.py`

**任务**:
1. 在 `app/models.py` 中新增 `AppConfig` 模型
2. 创建 `app/config_store.py` 和 `ConfigStore` 类
3. 实现 `get_config(key, fallback)`
4. 实现 `set_config(key, value)`
5. 实现 `load_from_json(key, fallback)` 和 `save_to_json(key, value)`
6. 实现 `get_config_store()` 单例函数

**验收**:
- `ConfigStore` 支持 MySQL 命中、未命中回填、JSON fallback
- `set_config` 始终写入 JSON，MySQL 可用时同时写入数据库

---

## T2: 创建 config_migration.py 迁移脚本

**文件**: `app/config_migration.py`

**任务**:
1. 定义配置映射（key → file path → default）
2. 实现 `migrate_configs_to_mysql()`
3. 检测数据库是否已有配置
4. 从 JSON 读取并写入 MySQL

**验收**:
- 幂等性：数据库已有数据时跳过
- 缺失配置时从 JSON 迁移

---

## T3: 在 main.py lifespan 中集成

**文件**: `app/main.py`

**任务**:
1. 在 MySQL 初始化后创建 `app_config` 表
2. 调用 `migrate_configs_to_mysql()`
3. 记录迁移日志

**验收**:
- 启动时自动创建配置表
- 自动迁移 JSON 配置

---

## T4: 修改配置 API

**文件**:
- `app/api/config.py`
- `app/api/ai_config.py`

**任务**:
1. `config.py` 的 `get_config` 和 `upload_config` 使用 `ConfigStore`
2. `ai_config.py` 的 `_load_ai_config` 和 `_save_ai_config` 使用 `ConfigStore`
3. 保持 API 接口签名不变

**验收**:
- 上传配置同时写入数据库和 JSON 文件
- 读取配置优先从数据库

---

## T5: 修改业务使用方

**文件**:
- `app/api/futures_analysis.py`
- `app/api/trade_review.py`
- `app/services/trade_parser.py`
- `app/services/plan_generator.py`
- `app/services/ai_analysis.py`

**任务**:
1. 替换所有 `_load_symbols_config()` / `load_symbols_config()` 为 `ConfigStore.get_config("symbols")`
2. 替换 `_load_ai_config()` 为 `ConfigStore.get_config("ai")`

**验收**:
- 所有读取点统一使用 `ConfigStore`
- 不修改业务逻辑

---

## T6: 编写测试用例

**文件**: `tests/test_config_store.py`

**任务**:
1. 测试 MySQL 命中场景
2. 测试 MySQL 未命中时读取 JSON 并回填
3. 测试 MySQL 不可用时读取 JSON
4. 测试 `set_config` 双写
5. 测试迁移幂等性
6. 运行全部测试套件确保无回归

**验收**:
- 所有测试通过
- 测试覆盖核心降级场景
