# 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<String>,
}

// 示例：用于创建 AI 分析结果的 DTO
#[api_dto]
pub struct NewAnalysisResultDto {
    pub symbol: String,
    pub module_id: String,
    pub model_name: Option<String>,
    pub content: String,
    pub meta_data: Option<serde_json::Value>,
}
```

## 5. 开发流程与工具链

本服务将完全遵循 `service_kit` 提供的标准化开发流程。
- **项目初始化**: 使用 `cargo generate --git <repo_url> service-template` 创建服务骨架。
- **质量保障**:
    - 代码风格检查: `cargo forge lint`
    - 单元与集成测试: `cargo forge test`
- **API 调试与交互**: 使用 `forge-cli` 工具，通过 `cargo forge <command>` 与正在运行的服务进行交互式 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`，说明如何本地启动、配置和测试该服务。
