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.
buffer_platform/docs/superpowers/specs/2026-07-04-analysis-storage...

5.9 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

comet_change role canonical_spec
analysis-storage-refactor technical-design openspec

Analysis Storage Refactor - Technical Design

1. 架构概览

1.1 目标架构

┌─────────────────────────────────────────────────────────────┐
│                     应用层                                   │
│  app/api/futures_analysis.py  ←→  app/services/cache.py     │
│                                         ↓                   │
│                                   StorageManager            │
│                                   (storage_manager.py)      │
└─────────────────────────────────────────────────────────────┘
                              ↓
        ┌─────────────────────┼─────────────────────┐
        ↓                     ↓                     ↓
   ┌─────────┐          ┌─────────┐          ┌─────────┐
   │  Redis  │          │  MySQL  │          │ SQLite  │
   │ (缓存)  │          │(持久化) │          │ (兜底)  │
   └─────────┘          └─────────┘          └─────────┘

1.2 核心组件

组件 职责
StorageManager 提供通用 Redis 缓存方法(cache_getcache_setcache_delete
analysis_db.py Analysis 数据库连接管理,根据后端可用性返回 MySQL 或 SQLite Session
analysis_models.py ORM 模型定义(不变)
analysis_migration.py SQLite → MySQL 数据迁移

1.3 表清单

表名 用途 缓存 TTL
futures_analysis 期货分析报告 5 分钟
watched_symbols 用户关注品种 10 分钟
ai_model_configs AI 模型配置 10 分钟
analysis_settings 分析设置 10 分钟
ai_analysis_cache AI 分析缓存 5 分钟
review_dates 复盘日期 1 小时
symbol_rankings 品种排名 1 小时
trading_plans 交易计划 1 小时
symbol_scores_v2 V2 品种评分 1 小时
trading_plans_v2 V2 交易计划 1 小时
sector_heat 板块热度 1 小时
review_plans_v2 V2 复盘计划 1 小时
trade_records 交易记录 不缓存
trade_import_batches 交易导入批次 不缓存

2. 降级策略

2.1 数据库 Session 切换

analysis_db.py 中的 get_analysis_db() 根据后端可用性返回不同 Session

业务代码 → get_analysis_db()
              ↓
        MySQL 可用?
        ↓ 是              ↓ 否
    MySQL Session    SQLite Session

2.2 Redis 缓存层(可选)

对于高频读取场景,业务代码可通过 StorageManager.cache_get/cache_set/cache_delete 使用 Redis

读取请求
    ↓
StorageManager.cache_get(key)
    ↓ 命中
返回数据
    ↓ 未命中
ORM 查询 MySQL/SQLite → StorageManager.cache_set(key, value) → 返回

2.3 降级状态检测

  • 复用 StorageManager.check_mysql() 惰性检测 MySQL 可用性
  • MySQL 不可用时,get_analysis_db() 返回 SQLite Session
  • 保留 SQLite 文件 data/futures_analysis.db 作为兜底

3. 数据迁移

3.1 迁移时机

应用启动时(lifespan),在 MySQL 表结构初始化后执行。

3.2 迁移逻辑

def migrate_analysis_sqlite_to_mysql():
    """将 SQLite analysis 数据迁移到 MySQL"""
    # 1. 检测 MySQL 表是否已有数据
    mysql_count = count_mysql_analysis_tables()
    if mysql_count > 0:
        logger.info("MySQL analysis 表已有数据,跳过迁移")
        return
    
    # 2. 从 SQLite 读取数据
    sqlite_data = read_sqlite_analysis_data()
    
    # 3. 批量写入 MySQL
    write_mysql_analysis_data(sqlite_data)
    
    logger.info("Analysis 数据迁移完成")

3.3 幂等性

  • 检测 MySQL 表是否已有数据
  • 有数据则跳过迁移
  • 迁移失败不影响应用启动

4. 缓存策略

4.1 通用缓存方法

StorageManager 提供三个通用方法:

  • cache_get(key): 读取 Redis 缓存
  • cache_set(key, value, ttl): 写入 Redis 缓存
  • cache_delete(key): 删除 Redis 缓存

4.2 缓存键设计

由业务代码决定缓存键,推荐格式:

analysis:{table_name}:{id}
analysis:{table_name}:list:{query_hash}

4.3 缓存失效

  • 写入时删除相关缓存
  • TTL 过期自动失效

4.4 缓存回填

  • 读取时未命中,查询 MySQL/SQLite 后回填
  • TTL 与表类型对应

5. 兼容性

5.1 ORM 模型

  • 保持不变
  • 使用 AnalysisBase 作为基类

5.2 API 接口

  • 保持不变
  • 通过 get_analysis_db() 依赖注入

5.3 SQLite 文件

  • 保留 data/futures_analysis.db
  • 降级时使用

6. 测试策略

6.1 单元测试

场景 测试方法
Redis 缓存命中 Mock Redis验证不查询 MySQL
Redis 缓存未命中 Mock Redis 返回 None验证查询 MySQL
MySQL 降级到 SQLite Mock MySQL 不可用,验证查询 SQLite
数据迁移 验证 SQLite 数据完整迁移到 MySQL

6.2 集成测试

  • 启动应用,验证 MySQL 表创建
  • 执行迁移,验证数据完整性
  • 调用 API验证功能正常

7. 风险与缓解

风险 缓解措施
数据迁移失败 保留 SQLite 作为降级方案,迁移失败时自动降级
Redis 缓存不一致 写入时先删缓存,再写 MySQL最后回填缓存
表结构不兼容 复用现有 ORM 模型MySQL 自动创建表结构
性能下降 Redis 缓存减少 MySQL 查询压力