diff --git a/openspec/changes/config-to-mysql/.comet.yaml b/openspec/changes/config-to-mysql/.comet.yaml new file mode 100644 index 0000000..73ad18d --- /dev/null +++ b/openspec/changes/config-to-mysql/.comet.yaml @@ -0,0 +1,24 @@ +workflow: full +phase: design +context_compression: off +build_mode: null +build_pause: null +subagent_dispatch: null +tdd_mode: null +review_mode: thorough +isolation: null +verify_mode: full +auto_transition: true +base_ref: f8d5ecd +design_doc: null +plan: null +verify_result: null +verification_report: null +branch_status: null +created_at: 2026-07-04 +verified_at: null +archived: false +handoff_context: null +handoff_hash: null +build_command: python -m pytest tests/ -v +verify_command: python -m pytest tests/ -v diff --git a/openspec/changes/config-to-mysql/.openspec.yaml b/openspec/changes/config-to-mysql/.openspec.yaml new file mode 100644 index 0000000..685dcee --- /dev/null +++ b/openspec/changes/config-to-mysql/.openspec.yaml @@ -0,0 +1,3 @@ +name: config-to-mysql +created: 2026-07-04 +status: active diff --git a/openspec/changes/config-to-mysql/design.md b/openspec/changes/config-to-mysql/design.md new file mode 100644 index 0000000..d3bd296 --- /dev/null +++ b/openspec/changes/config-to-mysql/design.md @@ -0,0 +1,101 @@ +# Design: Config to MySQL + +## 架构决策 + +### 决策 1:统一配置管理模块 + +**决策**:创建 `app/config_store.py` 作为所有配置读写的唯一入口。 + +**理由**: +- 消除多处重复的文件读取逻辑 +- 集中管理降级策略 +- 便于后续扩展(如缓存、审计) + +### 决策 2:单表存储键值对 + +**决策**:使用单表 `app_config` 存储所有配置,以 `config_key` 区分 `symbols` 和 `ai`。 + +**表结构**: +```sql +CREATE TABLE app_config ( + id INT PRIMARY KEY AUTO_INCREMENT, + config_key VARCHAR(64) UNIQUE NOT NULL, -- 'symbols' 或 'ai' + config_value JSON NOT NULL, + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP +) +``` + +**理由**: +- 与现有 JSON schema 兼容 +- 减少表数量 +- 未来新增配置无需改表结构 + +### 决策 3:MySQL + JSON 文件降级 + +**决策**:MySQL 可用时优先读写数据库;MySQL 不可用时回退到 JSON 文件。 + +**理由**: +- 用户明确要求无需 Redis +- JSON 文件作为 fallback 简单可靠 +- 与现有配置读取方式兼容 + +## 数据流 + +``` +业务代码 + ↓ +app/config_store.py + ↓ +MySQL 可用? + ↓ 是 ↓ 否 +读/写 app_config 读/写 JSON 文件 +``` + +## 配置键设计 + +| config_key | 对应文件 | 用途 | +|------------|----------|------| +| `symbols` | `config/symbols_config.json` | 品种合约映射 | +| `ai` | `config/ai_config.json` | AI 模型配置 | + +## 降级策略 + +### 读取流程 + +1. 检查 MySQL 可用性 +2. MySQL 可用则查询 `app_config` +3. 数据库无数据则读取 JSON 文件并回填数据库 +4. MySQL 不可用则直接读取 JSON 文件 + +### 写入流程 + +1. 检查 MySQL 可用性 +2. MySQL 可用则写入 `app_config` +3. 无论数据库是否成功,同步写入 JSON 文件(保持一致性) +4. MySQL 不可用则只写入 JSON 文件 + +## 兼容性 + +- 保持 `symbols_config.json` 和 `ai_config.json` 的 schema 不变 +- API 接口签名不变 +- 文件路径不变,作为 fallback 使用 + +## 数据迁移 + +启动时执行一次性迁移: + +1. 检测 `app_config` 表是否已有 `symbols` 和 `ai` 配置 +2. 缺失则从 JSON 文件读取并写入数据库 +3. 迁移幂等:已存在则跳过 + +## 测试策略 + +1. 单元测试: + - `ConfigStore.get_config` 从 MySQL 读取 + - `ConfigStore.get_config` 在 MySQL 不可用时读取 JSON + - `ConfigStore.set_config` 写入 MySQL 和 JSON + - 迁移幂等性 +2. 集成测试: + - 启动时自动创建表并迁移 + - API 接口正常工作 diff --git a/openspec/changes/config-to-mysql/proposal.md b/openspec/changes/config-to-mysql/proposal.md new file mode 100644 index 0000000..3a37a69 --- /dev/null +++ b/openspec/changes/config-to-mysql/proposal.md @@ -0,0 +1,59 @@ +# Proposal: Config to MySQL + +## 问题背景 + +当前配置信息(`symbols_config.json` 品种合约映射、`ai_config.json` AI 模型配置)以 JSON 文件形式存储在 `config/` 目录下。存在以下问题: + +1. **配置与应用状态分离**:文件配置难以统一备份、迁移和多实例共享 +2. **读写分散**:多个模块直接读取 JSON 文件,重复解析逻辑 +3. **无版本/审计**:文件修改无历史记录,难以追踪配置变更 +4. **与架构不一致**:行情数据和分析数据已迁移到 MySQL,配置仍停留在文件系统 + +## 目标 + +将 `symbols_config.json` 和 `ai_config.json` 迁移到 MySQL `buffer_platform` 数据库,提供统一的配置读取/写入接口,并保留 JSON 文件作为降级方案。 + +## 范围 + +### 包含 + +- 新增 MySQL 配置表:`symbol_config`、`ai_config` +- 创建统一配置管理模块 `app/config_store.py` +- 启动时自动迁移现有 JSON 配置到 MySQL +- 修改以下模块从数据库读取配置: + - `app/api/config.py` + - `app/api/ai_config.py` + - `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` +- MySQL 不可用时降级到 JSON 文件 + +### 不包含 + +- 新增业务功能 +- 修改配置结构(保持现有 JSON schema) +- Redis 缓存层 + +## 非目标 + +- 不改变配置 schema +- 不改变 API 接口签名 +- 不引入配置版本控制或审计日志 + +## 验收标准 + +1. 启动时自动创建配置表并迁移 JSON 数据到 MySQL +2. 所有配置读写通过 `app/config_store.py` 接口 +3. MySQL 不可用时自动降级到 JSON 文件 +4. 现有功能(品种列表、AI 配置、交易复盘、计划生成)正常工作 +5. 单元测试覆盖数据库命中、数据库未命中降级、迁移幂等性 + +## 风险 + +| 风险 | 缓解措施 | +|------|----------| +| 数据迁移失败 | 保留 JSON 文件作为降级方案 | +| 配置读取性能下降 | 配置数据量小,数据库查询足够快;无 Redis 需求 | +| 多处修改引入回归 | 统一封装 + 全面测试 | diff --git a/openspec/changes/config-to-mysql/tasks.md b/openspec/changes/config-to-mysql/tasks.md new file mode 100644 index 0000000..de39c05 --- /dev/null +++ b/openspec/changes/config-to-mysql/tasks.md @@ -0,0 +1,37 @@ +# Tasks: Config to MySQL + +## 1. 数据模型与配置存储模块 + +- [ ] 1.1 在 `app/models.py` 中新增 `AppConfig` 模型 +- [ ] 1.2 创建 `app/config_store.py`,实现 `ConfigStore` 类 +- [ ] 1.3 实现 `get_config(key)` 方法,支持 MySQL → JSON 降级 +- [ ] 1.4 实现 `set_config(key, value)` 方法,支持 MySQL + JSON 双写 +- [ ] 1.5 实现 `load_from_json(key, fallback)` 辅助方法 + +## 2. 数据迁移 + +- [ ] 2.1 创建 `app/config_migration.py`,实现 `migrate_configs_to_mysql()` +- [ ] 2.2 在 `app/main.py` lifespan 中创建 `app_config` 表 +- [ ] 2.3 在 `app/main.py` lifespan 中调用迁移函数 +- [ ] 2.4 迁移幂等性:数据库已有配置时跳过 + +## 3. 修改配置 API + +- [ ] 3.1 修改 `app/api/config.py` 使用 `ConfigStore` 读写 `symbols` 配置 +- [ ] 3.2 修改 `app/api/ai_config.py` 使用 `ConfigStore` 读写 `ai` 配置 +- [ ] 3.3 保持 API 接口签名不变 + +## 4. 修改业务使用方 + +- [ ] 4.1 修改 `app/api/futures_analysis.py` 从 `ConfigStore` 读取品种配置 +- [ ] 4.2 修改 `app/api/trade_review.py` 从 `ConfigStore` 读取品种配置 +- [ ] 4.3 修改 `app/services/trade_parser.py` 从 `ConfigStore` 读取品种配置 +- [ ] 4.4 修改 `app/services/plan_generator.py` 从 `ConfigStore` 读取品种配置 +- [ ] 4.5 修改 `app/services/ai_analysis.py` 从 `ConfigStore` 读取 AI 配置 + +## 5. 测试与验证 + +- [ ] 5.1 编写 `tests/test_config_store.py`,覆盖 MySQL 命中/未命中/降级场景 +- [ ] 5.2 编写迁移测试,验证幂等性 +- [ ] 5.3 运行全部测试套件,确保无回归 +- [ ] 5.4 启动应用验证配置读取正常