From 4956086d845bd0a9ad01c2a747304f8df5e6ac91 Mon Sep 17 00:00:00 2001 From: Lxy Date: Sat, 4 Jul 2026 23:08:47 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E5=88=9B=E5=BB=BA=20config-to-mysql=20?= =?UTF-8?q?Design=20Doc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2026-07-04-config-to-mysql-design.md | 186 ++++++++++++++++++ openspec/changes/config-to-mysql/.comet.yaml | 4 +- .../.comet/handoff/brainstorm-summary.md | 31 +++ 3 files changed, 219 insertions(+), 2 deletions(-) create mode 100644 docs/superpowers/specs/2026-07-04-config-to-mysql-design.md create mode 100644 openspec/changes/config-to-mysql/.comet/handoff/brainstorm-summary.md diff --git a/docs/superpowers/specs/2026-07-04-config-to-mysql-design.md b/docs/superpowers/specs/2026-07-04-config-to-mysql-design.md new file mode 100644 index 0000000..b883a8d --- /dev/null +++ b/docs/superpowers/specs/2026-07-04-config-to-mysql-design.md @@ -0,0 +1,186 @@ +--- +comet_change: config-to-mysql +role: technical-design +canonical_spec: openspec +--- + +# Config to MySQL - Technical Design + +## 1. 架构概览 + +### 1.1 目标架构 + +``` +业务代码 / API + ↓ +app/config_store.py (统一入口) + ↓ +MySQL 可用? + ↓ 是 ↓ 否 +读/写 app_config 读/写 JSON 文件 +``` + +### 1.2 核心组件 + +| 组件 | 职责 | +|------|------| +| `AppConfig` 模型 | MySQL 配置表 ORM 映射 | +| `ConfigStore` | 统一配置读写入口,封装降级逻辑 | +| `config_migration.py` | JSON → MySQL 一次性迁移 | +| JSON 文件 | MySQL 不可用时降级使用 | + +## 2. 数据模型 + +### 2.1 AppConfig 表 + +```python +class AppConfig(Base): + __tablename__ = "app_config" + + id = Column(Integer, primary_key=True, autoincrement=True) + config_key = Column(String(64), unique=True, nullable=False, index=True) + config_value = Column(JSON, nullable=False) + updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) + created_at = Column(DateTime, default=datetime.utcnow) +``` + +### 2.2 配置键 + +| config_key | 对应文件 | 默认值 | +|------------|----------|--------| +| `symbols` | `config/symbols_config.json` | `{"futures": {}, "stock": {}}` | +| `ai` | `config/ai_config.json` | `{"models": [], "active_model": None, "analysis_settings": {...}}` | + +## 3. 降级策略 + +### 3.1 读取流程 + +1. 检查 MySQL 可用性(复用 `StorageManager.check_mysql()`) +2. MySQL 可用: + - 查询 `app_config` + - 命中则返回 + - 未命中则读取 JSON 文件并回填数据库 +3. MySQL 不可用: + - 直接读取 JSON 文件 + +### 3.2 写入流程 + +1. 始终写入 JSON 文件(保证 fallback 最新) +2. MySQL 可用时同时写入 `app_config` +3. MySQL 不可用时跳过数据库写入 + +### 3.3 降级检测 + +复用 `StorageManager.check_mysql()` 惰性检测,避免每次配置读写都尝试连接数据库。 + +## 4. ConfigStore 接口 + +```python +class ConfigStore: + def get_config(self, key: str, fallback: Optional[dict] = None) -> dict: ... + def set_config(self, key: str, value: dict) -> bool: ... + def load_from_json(self, key: str, fallback: Optional[dict] = None) -> dict: ... + def save_to_json(self, key: str, value: dict) -> None: ... +``` + +### 4.1 单例获取 + +```python +_config_store = None + +def get_config_store() -> ConfigStore: + global _config_store + if _config_store is None: + _config_store = ConfigStore() + return _config_store +``` + +## 5. 数据迁移 + +### 5.1 迁移时机 + +应用启动时(`lifespan`),在 MySQL 表结构初始化后执行。 + +### 5.2 迁移逻辑 + +```python +def migrate_configs_to_mysql(): + for key, file_path, default in CONFIGS: + if _config_exists_in_mysql(key): + continue + value = _load_json(file_path, default) + _save_to_mysql(key, value) +``` + +### 5.3 幂等性 + +- 检测 `app_config` 是否已有对应 key +- 有则跳过 + +## 6. 使用方修改 + +### 6.1 品种配置读取 + +替换以下文件中的 `_load_symbols_config()` / `load_symbols_config()`: + +- `app/api/config.py` +- `app/api/futures_analysis.py` +- `app/api/trade_review.py` +- `app/services/trade_parser.py` +- `app/services/plan_generator.py` + +统一使用: + +```python +from app.config_store import get_config_store + +symbols = get_config_store().get_config("symbols", {"futures": {}, "stock": {}}) +``` + +### 6.2 AI 配置读取 + +替换 `app/api/ai_config.py` 和 `app/services/ai_analysis.py` 中的 `_load_ai_config()`: + +```python +ai_config = get_config_store().get_config("ai", {...default...}) +``` + +### 6.3 写入接口 + +`app/api/config.py` 和 `app/api/ai_config.py` 的保存接口改为: + +```python +get_config_store().set_config("symbols", data) +``` + +## 7. 兼容性 + +- 保持 JSON 文件路径和 schema 不变 +- API 接口签名不变 +- 默认值与现有 JSON 默认值一致 + +## 8. 测试策略 + +### 8.1 单元测试 + +| 场景 | 测试 | +|------|------| +| MySQL 命中 | `get_config` 从数据库返回值 | +| MySQL 未命中 | `get_config` 读取 JSON 并回填 | +| MySQL 不可用 | `get_config` 读取 JSON | +| 写入 | `set_config` 双写数据库和文件 | +| 迁移幂等 | 数据库已有数据时跳过 | + +### 8.2 集成测试 + +- 启动应用验证配置表创建 +- 验证 API 读写正常 +- 运行全部测试套件确保无回归 + +## 9. 风险与缓解 + +| 风险 | 缓解措施 | +|------|----------| +| MySQL 不可用时配置无法写入数据库 | 始终同步写入 JSON 文件 | +| 多处修改引入回归 | 统一 `ConfigStore` 接口 + 全面测试 | +| JSON 文件与数据库不一致 | 写入时双写;读取时优先数据库 | diff --git a/openspec/changes/config-to-mysql/.comet.yaml b/openspec/changes/config-to-mysql/.comet.yaml index 73ad18d..cc704b9 100644 --- a/openspec/changes/config-to-mysql/.comet.yaml +++ b/openspec/changes/config-to-mysql/.comet.yaml @@ -1,5 +1,5 @@ workflow: full -phase: design +phase: build context_compression: off build_mode: null build_pause: null @@ -10,7 +10,7 @@ isolation: null verify_mode: full auto_transition: true base_ref: f8d5ecd -design_doc: null +design_doc: docs/superpowers/specs/2026-07-04-config-to-mysql-design.md plan: null verify_result: null verification_report: null diff --git a/openspec/changes/config-to-mysql/.comet/handoff/brainstorm-summary.md b/openspec/changes/config-to-mysql/.comet/handoff/brainstorm-summary.md new file mode 100644 index 0000000..443783c --- /dev/null +++ b/openspec/changes/config-to-mysql/.comet/handoff/brainstorm-summary.md @@ -0,0 +1,31 @@ +# Brainstorm Summary + +## 确认的技术方案 + +**采用方案:单表键值对 + 统一配置模块 + JSON fallback** + +| 组件 | 说明 | +|------|------| +| `app/models.py` | 新增 `AppConfig` 模型 | +| `app/config_store.py` | 统一配置读写入口 | +| `app/config_migration.py` | JSON → MySQL 迁移脚本 | +| JSON 文件 | 降级方案,保留原路径 | + +## 关键取舍与风险 + +| 取舍 | 决策 | +|------|------| +| 单表 vs 多表 | 单表,通过 `config_key` 区分,未来扩展无需改表 | +| 是否使用 Redis | 不使用,按用户要求仅 MySQL | +| 是否保留文件 | 保留,作为 MySQL 不可用时的降级 | +| 写入策略 | 双写:MySQL 可用时写数据库 + 写文件;MySQL 不可用时只写文件 | + +## 测试策略 + +- 单元测试:`tests/test_config_store.py` 覆盖读取、写入、降级 +- 迁移测试:验证幂等性 +- 回归测试:全部测试套件 + +## Spec Patch + +无