convertor/api-server/docs/ARCHITECTURE.md

328 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ConvertX API 架構說明
## 系統架構圖
```
┌─────────────────────────────────────────────────────────────────┐
│ API Server │
│ │
│ ┌──────────────┐ │
│ │ Auth Layer │◄──── JWT Token 驗證 │
│ │ (JWT) │ │
│ └──────┬───────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Request Router │ │
│ │ │ │
│ │ ┌─────────────┐ ┌──────────────────┐ │ │
│ │ │ REST API │ │ GraphQL API │ │ │
│ │ │ /api/v1/* │ │ /graphql │ │ │
│ │ └──────┬──────┘ └────────┬─────────┘ │ │
│ │ │ │ │ │
│ └──────────┼─────────────────────────┼──────────────────┘ │
│ │ │ │
│ └────────────┬────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────┐ │
│ │ Conversion Service │ │
│ │ (Domain Logic) │ │
│ │ │ │
│ │ ┌─────────────────┐ │ │
│ │ │ Engine Registry │ │ │
│ │ └─────────────────┘ │ │
│ └───────────┬───────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────┐ │
│ │ External Converters │ │
│ │ (FFmpeg, etc.) │ │
│ └───────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
┌───────────────────────┐
│ File Storage │
│ ┌─────────────────┐ │
│ │ data/uploads/ │ │
│ │ data/output/ │ │
│ └─────────────────┘ │
└───────────────────────┘
```
## 模組說明
### 1. Auth Layer (`src/auth.rs`)
負責所有請求的 JWT 驗證。
**職責**
- 解析 Authorization Header
- 驗證 JWT Token 簽名
- 檢查 Token 是否過期
- 提取使用者資訊
**不負責**
- 產生 JWT Token由外部認證服務處理
- 使用者管理
### 2. REST API (`src/rest.rs`)
提供 RESTful HTTP 端點。
**端點**
- `GET /health` - 健康檢查
- `GET /api/v1/engines` - 列出引擎
- `POST /api/v1/convert` - 建立轉檔任務
- `GET /api/v1/jobs` - 列出任務
- `GET /api/v1/jobs/:id` - 取得任務狀態
- `GET /api/v1/jobs/:id/download` - 下載結果
- `DELETE /api/v1/jobs/:id` - 刪除任務
### 3. GraphQL API (`src/graphql.rs`)
提供 GraphQL 查詢與變更。
**Queries**
- `health` - 健康檢查
- `engines` - 列出引擎
- `engine(id)` - 取得特定引擎
- `jobs` - 列出任務
- `job(id)` - 取得特定任務
- `validateConversion` - 驗證轉換
- `suggestions` - 取得建議
**Mutations**
- `createJob` - 建立任務
- `deleteJob` - 刪除任務
### 4. Engine Registry (`src/engine.rs`)
管理所有可用的轉換引擎及其能力。
**職責**
- 註冊引擎及其支援的格式
- 驗證轉換是否可行
- 提供替代方案建議
**設計原則**
- 引擎必須明確指定,不自動選擇
- 不支援的轉換必須回傳建議
### 5. Conversion Service (`src/conversion.rs`)
處理轉檔任務的核心邏輯。
**職責**
- 建立和管理轉檔任務
- 儲存上傳的檔案
- 呼叫外部轉換程式
- 管理輸出檔案
### 6. Error Handling (`src/error.rs`)
統一的錯誤處理機制。
**特色**
- 結構化的錯誤回應
- 錯誤碼分類
- 轉換建議整合
## 資料流程
### 轉檔請求流程
```
Client Request
┌─────────────────┐
│ JWT Validation │ ──────► 401 Unauthorized
└────────┬────────┘
│ Valid
┌─────────────────┐
│ Parse Request │ ──────► 400 Bad Request
│ (file, engine, │
│ target_format) │
└────────┬────────┘
│ Valid
┌─────────────────┐
│ Validate │ ──────► 422 Unsupported
│ Conversion │ (with suggestions)
│ (Engine Registry)│
└────────┬────────┘
│ Supported
┌─────────────────┐
│ Create Job │
│ Save File │
│ Start Conversion│
└────────┬────────┘
┌─────────────────┐
│ 201 Created │
│ Return Job ID │
└─────────────────┘
```
### 轉換執行流程
```
Background Task
┌─────────────────┐
│ Update Status │
│ → Processing │
└────────┬────────┘
┌─────────────────┐
│ Execute │
│ Converter │
│ Command │
└────────┬────────┘
┌────┴────┐
│ │
▼ ▼
┌───────┐ ┌───────┐
│Success│ │Failed │
└───┬───┘ └───┬───┘
│ │
▼ ▼
┌───────┐ ┌───────┐
│Update │ │Update │
│Status │ │Status │
│=Done │ │=Failed│
└───────┘ └───────┘
```
## 設計決策
### 1. 為什麼使用 Rust
- **效能**:處理大量並發請求時表現優異
- **記憶體安全**:避免常見的記憶體問題
- **非同步支援**Tokio 生態系統成熟
- **類型安全**:編譯時檢查減少運行時錯誤
### 2. 為什麼同時支援 REST 和 GraphQL
- **REST**:簡單直觀,適合檔案上傳/下載
- **GraphQL**:靈活查詢,減少 over-fetching
- **獨立使用**:使用者可選擇適合的 API
### 3. 為什麼採用「結果僅透過 API 下載」策略?
- **安全性**:不暴露檔案系統路徑
- **權限控制**:下載時驗證身份
- **彈性部署**:易於整合 CDN 或雲端儲存
- **可擴展性**:未來可改用分散式儲存
### 4. 為什麼引擎必須明確指定?
- **可預測性**:使用者明確知道使用什麼工具
- **一致性**:避免因自動選擇導致的結果差異
- **透明度**:錯誤時能明確指出是哪個引擎的問題
## 擴展指南
### 新增轉換引擎
1.`src/engine.rs``register_default_engines()` 中新增:
```rust
let new_engine = Engine::new(
"engine_id",
"Engine Name",
"Engine description"
)
.add_conversion("input_format", vec!["output1", "output2"]);
self.register(new_engine);
```
2.`src/conversion.rs``run_converter_command()` 中新增命令:
```rust
"engine_id" => (
"command",
vec!["arg1".to_string(), input, output],
),
```
### 新增 REST 端點
`src/rest.rs` 中:
```rust
pub fn routes() -> Router<AppState> {
Router::new()
.route("/api/v1/new-endpoint", get(new_handler))
// ...
}
async fn new_handler(
State(state): State<AppState>,
RequireAuth(user): RequireAuth,
) -> ApiResult<impl IntoResponse> {
// ...
}
```
### 新增 GraphQL 查詢/變更
`src/graphql.rs` 中:
```rust
#[Object]
impl QueryRoot {
async fn new_query(&self, ctx: &Context<'_>) -> GqlResult<SomeType> {
let _user = validate_auth(ctx)?;
// ...
}
}
#[Object]
impl MutationRoot {
async fn new_mutation(&self, ctx: &Context<'_>, input: Input) -> GqlResult<Output> {
let user = validate_auth(ctx)?;
// ...
}
}
```
## 效能考量
### 並發處理
- 使用 Tokio 非同步運行時
- 轉換任務在背景執行
- 任務狀態儲存在記憶體(生產環境應使用資料庫)
### 檔案處理
- 大檔案直接寫入磁碟,不佔用過多記憶體
- 輸出檔案串流下載
### 未來優化方向
1. 使用 Redis 進行任務佇列
2. 使用 PostgreSQL 進行任務持久化
3. 實作任務優先級
4. 新增任務取消功能
5. 實作 Webhook 回呼