# Rust 数据持久化服务设计 (`rust_data_service_design.md`) ## 1. 服务定位与核心职责 - **服务名称**: `data-persistence-service` - **核心定位**: 本服务是整个微服务架构中**唯一的数据持久化层**。它是数据库的**独占所有者 (Sole Owner)**,负责管理所有与数据库的交互。 ### 1.1. 职责边界:核心实体服务 本服务被设计为**核心实体数据服务**,而非一个包罗万象的、管理所有数据的“上帝服务”。它的职责被严格限定在管理那些**跨多个业务领域共享的核心数据实体**上。 这种设计遵循了一种务实的**混合微服务数据模式**: - **核心数据集中管理**: 保证了通用数据的唯一性和一致性。我们定义的核心实体包括: - 公司基本信息 (`company_profiles`) - 标准化财务数据 (`time_series_financials`) - 标准化市场数据 (`daily_market_data`) - AI分析结果 (`analysis_results`) - 作为一种可被多方消费的核心产出物。 - **业务数据独立持久化**: 未来新增的、具有独立业务领域的微服务(例如“量化回测服务”)将被**允许并鼓励拥有和管理自己的数据库 Schema 或表**。这些新服务在需要核心实体数据时,应通过调用本服务提供的 API 来获取,而不是直接连接数据库。 这一策略确保了核心数据的一致性,同时为新服务的独立开发和快速迭代提供了最大的灵活性。 ## 2. 技术选型与开发范式 ### 2.1. 核心技术栈 - **语言**: **Rust** - **开发套件**: **`service_kit`** (项目内置的一站式微服务开发套件) - **Web 框架**: **`axum`** - **数据库交互**: **`sqlx`** - **序列化/反序列化**: **`serde`** (由 `service_kit` 自动集成) ### 2.2. 开发范式:API 规范驱动 我们将采纳 `service_kit` 提供的、以 **OpenAPI** 规范为核心的开发范式。 - **数据契约**: 所有的数据传输对象 (DTOs) 都将使用 `service_kit` 提供的 `#[api_dto]` 宏进行标注。此宏会自动派生 `serde` 和 `utoipa::ToSchema`,确保我们的 Rust 代码即是 API 规范的“唯一事实源”。 - **前后端协同**: 我们将使用 `cargo forge generate-types` 命令,从服务自动生成的 OpenAPI 规范中,为前端项目生成 TypeScript 类型定义,实现端到端的类型安全。 - **数据交换格式**: 服务间的数据交换格式依然是 **JSON**。 ## 3. API 端点设计 (API Endpoint Design) API 的设计严格服务于对核心实体的通用读写操作。 --- ### 3.1. 公司信息 (`/companies`) - **对应表**: `company_profiles` | Method | Endpoint | 描述 | | :--- | :--- | :--- | | `PUT` | `/api/v1/companies` | 创建或更新(Upsert)一个公司的基本信息 | | `GET` | `/api/v1/companies/{symbol}` | 获取指定公司的基本信息 | --- ### 3.2. 市场与财务数据 (`/market-data`) - **对应表**: `time_series_financials`, `daily_market_data` | Method | Endpoint | 描述 | | :--- | :--- | :--- | | `POST` | `/api/v1/market-data/financials/batch` | 批量写入多条时间序列财务指标 | | `GET` | `/api/v1/market-data/financials/{symbol}` | 查询某公司的财务指标 (支持按 `metrics`, `start_date`, `end_date` 过滤) | | `POST` | `/api/v1/market-data/daily/batch` | 批量写入多条每日市场行情数据 | | `GET` | `/api/v1/market-data/daily/{symbol}` | 查询某公司的每日行情 (支持按 `start_date`, `end_date` 过滤) | --- ### 3.3. AI 分析结果 (`/analysis-results`) - **对应表**: `analysis_results` | Method | Endpoint | 描述 | | :--- | :--- | :--- | | `POST` | `/api/v1/analysis-results` | 保存一条新的 AI 分析结果 | | `GET` | `/api/v1/analysis-results` | 查询分析结果列表 (支持按 `symbol`, `module_id` 过滤) | | `GET` | `/api/v1/analysis-results/{id}` | 获取单条分析结果的详情 | --- ### 3.4. 系统配置 (`/system-config`) - **对应表**: `system_config` | Method | Endpoint | 描述 | | :--- | :--- | :--- | | `PUT` | `/api/v1/system-config/{key}` | 创建或更新一条键值对配置 | | `GET` | `/api/v1/system-config/{key}` | 获取一条键值对配置 | ## 4. 数据传输对象 (DTOs) 所有 API 的请求体和响应体都将使用 `service_kit` 的 `#[api_dto]` 宏进行定义,以自动获得序列化、API Schema 生成和调试能力。 ```rust use service_kit::macros::api_dto; // 示例:用于批量写入财务数据的 DTO #[api_dto] pub struct TimeSeriesFinancialDto { pub symbol: String, pub metric_name: String, pub period_date: chrono::NaiveDate, pub value: f64, pub source: Option, } // 示例:用于创建 AI 分析结果的 DTO #[api_dto] pub struct NewAnalysisResultDto { pub symbol: String, pub module_id: String, pub model_name: Option, pub content: String, pub meta_data: Option, } ``` ## 5. 开发流程与工具链 本服务将完全遵循 `service_kit` 提供的标准化开发流程。 - **项目初始化**: 使用 `cargo generate --git service-template` 创建服务骨架。 - **质量保障**: - 代码风格检查: `cargo forge lint` - 单元与集成测试: `cargo forge test` - **API 调试与交互**: 使用 `forge-cli` 工具,通过 `cargo forge ` 与正在运行的服务进行交互式 API 调用和调试。 - **前端协同**: 在 CI/CD 流程或本地开发中,通过 `cargo forge generate-types` 命令,自动将本服务的 API 类型同步到前端项目。 ## 6. 项目结构(建议) ``` /data-persistence-service ├── Cargo.toml └── src/ ├── main.rs # 应用入口, 初始化数据库连接池, 定义路由 ├── error.rs # 统一的错误处理类型 ├── db.rs # 数据库交互逻辑 (使用 sqlx) ├── models.rs # 数据库表对应的结构体 ├── dtos.rs # API 请求/响应对应的结构体 └── api/ ├── mod.rs ├── companies.rs ├── market_data.rs └── analysis.rs ``` ## 7. 实施计划 (Implementation Plan & To-Do List) 本部分将开发 `data-persistence-service` 的过程分解为一系列可执行、可追踪的任务。 ### Phase 1: 项目初始化与基础设置 - [x] **T1.1**: 使用 `cargo generate` 和 `service-template` 在 `services/data-persistence-service` 目录下初始化新项目。 - [x] **T1.2**: 清理模板中的示例代码(如 `hello` 模块)。 - [x] **T1.3**: 配置 `Cargo.toml`,添加 `sqlx` (with `postgres`, `runtime-tokio-rustls`, `chrono`, `uuid`, `json`), `axum`, `tokio`, `serde` 等核心依赖。 - [x] **T1.4**: 设置 `.env` 文件,用于管理 `DATABASE_URL` 等环境变量。 - [x] **T1.5**: 在 `main.rs` 中建立与 PostgreSQL 的数据库连接池 (`sqlx::PgPool`)。 ### Phase 2: 数据库集成与迁移 - [x] **T2.1**: 安装 `sqlx-cli` (`cargo install sqlx-cli`)。 - [x] **T2.2**: 使用 `sqlx-cli` 初始化迁移目录 (`sqlx migrate add create_initial_tables`)。 - [x] **T2.3**: 在生成的迁移 SQL 文件中,编写 `CREATE TABLE` 语句,创建 `docs/database_schema_design.md` 中定义的所有表 (`company_profiles`, `time_series_financials` 等)。 - [x] **T2.4**: 在迁移 SQL 文件中,为时序表 (`time_series_financials`, `daily_market_data`) 添加 `create_hypertable` 命令。 - [x] **T2.5**: 运行 `sqlx migrate run` 应用迁移,并在数据库中验证表结构是否正确创建。 - [x] **T2.6**: 在 `src/models.rs` 中,根据数据库表结构,编写对应的 Rust 结构体。 ### Phase 3: 核心 API 实现 - [x] **T3.1**: **Companies API**: - [x] 在 `src/dtos.rs` 中创建 `CompanyProfileDto`。 - [x] 在 `src/db.rs` 中实现 `upsert_company` 和 `get_company_by_symbol` 数据库操作函数。 - [x] 在 `src/api/companies.rs` 中创建 `PUT /api/v1/companies` 和 `GET /api/v1/companies/{symbol}` 的 `axum` handler,并连接到 `db` 函数。 - [x] **T3.2**: **Market Data API**: - [x] 在 `src/dtos.rs` 中创建 `TimeSeriesFinancialDto` 和 `DailyMarketDataDto`。 - [x] 在 `src/db.rs` 中实现 `batch_insert_financials` 和 `get_financials_by_symbol` 函数。 - [x] 在 `src/db.rs` 中实现 `batch_insert_daily_data` 和 `get_daily_data_by_symbol` 函数。 - [x] 在 `src/api/market_data.rs` 中创建对应的 `axum` handlers 和路由。 - [x] **T3.3**: **Analysis Results API**: - [x] 在 `src/dtos.rs` 中创建 `NewAnalysisResultDto` 和 `AnalysisResultDto`。 - [x] 在 `src/db.rs` 中实现 `create_analysis_result` 和 `get_analysis_results` 函数。 - [x] 在 `src/api/analysis.rs` 中创建对应的 `axum` handlers 和路由。 - [x] **T3.4**: 在 `main.rs` 中,将所有 API 路由组合起来。 ### Phase 4: 容器化与集成 - [x] **T4.1**: 编写多阶段 `Dockerfile`,优化镜像大小和构建速度。 - [x] **T4.2**: 在根目录的 `docker-compose.yml` 中,添加 `data-persistence-service` 的定义,并配置其依赖 `postgres-db`。 - [x] **T4.3**: 修改 `Tiltfile` 以包含新的 Rust 服务,确保 `tilt up` 可以成功构建并运行该服务。 - [x] **T4.4**: **(集成点)** 修改现有的 Python `backend` 服务,使其不再直接连接数据库,而是通过 HTTP 请求调用 `data-persistence-service` 的 API 来读写数据。 ### Phase 5: 测试与文档 - [x] **T5.1**: 为 `db.rs` 中的每个数据库操作函数编写单元测试(需要 `sqlx` 的 test-macros 特性)。 - [x] **T5.2**: 为每个 API 端点编写集成测试。 - [ ] **T5.3**: 使用 `#[api_dto]` 宏确保所有 DTO 都已正确集成到 OpenAPI 规范中。 - [ ] **T5.4**: 运行 `cargo forge generate-types`,验证能否成功生成 TypeScript 类型文件。 - [ ] **T5.5**: 编写 `README.md`,说明如何本地启动、配置和测试该服务。