docs: Add Python and Node.js integration specification
- Architecture overview for mixed runtime environments - Python version management with venv - Node.js version locking for n8n - Isolation principles for coexisting environments - Workflow integration patterns - Monitoring configuration - Troubleshooting guide - New service decision tree
This commit is contained in:
@@ -210,8 +210,6 @@ async fn good_practice() {
|
|||||||
|
|
||||||
## 5. 外部程序整合
|
## 5. 外部程序整合
|
||||||
|
|
||||||
### 5.1 Python 腳本呼叫
|
|
||||||
|
|
||||||
當需要使用 Python 生態系工具 (如 faster-whisper, YOLO) 時:
|
當需要使用 Python 生態系工具 (如 faster-whisper, YOLO) 時:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
@@ -275,7 +273,289 @@ for line in stderr.lines() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## 6. 測試策略
|
---
|
||||||
|
|
||||||
|
## 6. Python 與 Node.js 混用規範
|
||||||
|
|
||||||
|
本專案同時使用 Python 和 Node.js (n8n),需建立明確的版本隔離與管理規範。
|
||||||
|
|
||||||
|
### 6.1 架構概述
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ Momentry Core │
|
||||||
|
│ │
|
||||||
|
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||||
|
│ │ Rust │ │ Python │ │ Node.js │ │
|
||||||
|
│ │ (Core) │───▶ │ (Scripts) │ │ (n8n) │ │
|
||||||
|
│ │ │ │ │ │ │ │
|
||||||
|
│ │ - CLI │ │ - ASR │ │ - Workflow │ │
|
||||||
|
│ │ - DB │ │ - Thumb │ │ - API │ │
|
||||||
|
│ │ - Storage │ │ - OCR │ │ - Webhooks │ │
|
||||||
|
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||||
|
│ │ │ │ │
|
||||||
|
│ ▼ ▼ ▼ │
|
||||||
|
│ ┌─────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ 資料庫 / 檔案系統 / Qdrant │ │
|
||||||
|
│ └─────────────────────────────────────────────────────┘ │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.2 Python 版本管理
|
||||||
|
|
||||||
|
#### 6.2.1 版本鎖定
|
||||||
|
|
||||||
|
| 版本 | 用途 | 路徑 |
|
||||||
|
|------|------|------|
|
||||||
|
| 3.11.14 | 影片處理腳本 | `/opt/homebrew/bin/python3.11` |
|
||||||
|
|
||||||
|
#### 6.2.2 虛擬環境
|
||||||
|
|
||||||
|
使用專案隔離的 venv:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 建立虛擬環境
|
||||||
|
cd /Users/accusys/momentry_core_0.1
|
||||||
|
python3.11 -m venv venv
|
||||||
|
|
||||||
|
# 啟用
|
||||||
|
source venv/bin/activate
|
||||||
|
|
||||||
|
# 安裝依賴
|
||||||
|
pip install faster-whisper opencv-python python-dotenv
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 6.2.3 Rust 呼叫 Python
|
||||||
|
|
||||||
|
```rust
|
||||||
|
let venv_python = Path::new(env!("CARGO_MANIFEST_DIR"))
|
||||||
|
.join("venv")
|
||||||
|
.join("bin")
|
||||||
|
.join("python");
|
||||||
|
|
||||||
|
let output = Command::new(venv_python)
|
||||||
|
.arg(script_path)
|
||||||
|
.arg(video_path)
|
||||||
|
.output()
|
||||||
|
.context("Failed to run Python script")?;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.3 Node.js 版本管理
|
||||||
|
|
||||||
|
#### 6.3.1 版本鎖定
|
||||||
|
|
||||||
|
參考 `docs/NODEJS.md`:
|
||||||
|
|
||||||
|
| 版本 | 用途 | 路徑 |
|
||||||
|
|------|------|------|
|
||||||
|
| 22.22.1 | n8n | `/opt/homebrew/opt/node@22/bin/node` |
|
||||||
|
|
||||||
|
#### 6.3.2 n8n 服務配置
|
||||||
|
|
||||||
|
使用 launchd plist 隔離:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<!-- com.momentry.n8n.main.plist -->
|
||||||
|
<key>ProgramArguments</key>
|
||||||
|
<array>
|
||||||
|
<string>/opt/homebrew/opt/node@22/bin/node</string>
|
||||||
|
<string>/opt/homebrew/lib/node_modules/n8n/bin/n8n</string>
|
||||||
|
<string>start</string>
|
||||||
|
</array>
|
||||||
|
|
||||||
|
<key>EnvironmentVariables</key>
|
||||||
|
<dict>
|
||||||
|
<key>PATH</key>
|
||||||
|
<string>/opt/homebrew/opt/node@22/bin:/opt/homebrew/bin:...</string>
|
||||||
|
</dict>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.4 Python + Node.js 共存原則
|
||||||
|
|
||||||
|
#### 6.4.1 隔離原則
|
||||||
|
|
||||||
|
| 原則 | 說明 |
|
||||||
|
|------|------|
|
||||||
|
| **獨立路徑** | Python 用 venv 路徑,Node.js 用 node@22 路徑 |
|
||||||
|
| **獨立環境** | n8n 服務使用 launchd plist,不與 Rust 共享環境 |
|
||||||
|
| **明確版本** | 所有腳本明確指定直譯器路徑 |
|
||||||
|
| **PORT 分配** | n8n: 5678/5690, API: 另行分配 |
|
||||||
|
|
||||||
|
#### 6.4.2 環境變數隔離
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Rust 專案 .env
|
||||||
|
DATABASE_URL=postgres://...
|
||||||
|
|
||||||
|
# n8n plist
|
||||||
|
N8N_ENCRYPTION_KEY=xxx
|
||||||
|
N8N_BASIC_AUTH_ACTIVE=true
|
||||||
|
|
||||||
|
# 勿混用,避免 Rust 讀到 n8n 環境變數
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.5 工作流程整合
|
||||||
|
|
||||||
|
#### 6.5.1 Rust → Python
|
||||||
|
|
||||||
|
```
|
||||||
|
Rust CLI ──▶ Python Script ──▶ JSON Output ──▶ Rust Parse
|
||||||
|
│ │
|
||||||
|
└── venv/bin/python └── faster-whisper
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 6.5.2 Rust → n8n Webhook
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// 觸發 n8n workflow
|
||||||
|
use reqwest;
|
||||||
|
|
||||||
|
pub async fn trigger_n8n_webhook(webhook_url: &str, payload: &str) -> Result<()> {
|
||||||
|
let client = reqwest::Client::new();
|
||||||
|
client.post(webhook_url)
|
||||||
|
.json(payload)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.context("Failed to trigger n8n webhook")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 6.5.3 n8n → Rust API
|
||||||
|
|
||||||
|
```
|
||||||
|
n8n Workflow ──▶ HTTP Request Node ──▶ Rust API Server
|
||||||
|
│
|
||||||
|
┌───────┴───────┐
|
||||||
|
│ axum server │
|
||||||
|
│ /api/webhook │
|
||||||
|
└───────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.6 監控配置
|
||||||
|
|
||||||
|
#### 6.6.1 獨立監控腳本
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# monitor/service/node_monitor.sh
|
||||||
|
# 監控 n8n Node.js 版本
|
||||||
|
|
||||||
|
# monitor/service/python_monitor.sh
|
||||||
|
# 監控 Python 腳本執行狀態
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 6.6.2 健康檢查
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# monitor_config.yaml
|
||||||
|
services:
|
||||||
|
- name: "n8n"
|
||||||
|
type: "http"
|
||||||
|
port: 5678
|
||||||
|
check_url: "http://localhost:5678/"
|
||||||
|
|
||||||
|
- name: "Python Scripts"
|
||||||
|
type: "process"
|
||||||
|
check: "pgrep -f asr_processor.py"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.7 排程管理
|
||||||
|
|
||||||
|
#### 6.7.1 備份排程 (Python 腳本)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# crontab
|
||||||
|
0 3 * * * /Users/accusys/momentry/scripts/backup_all.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 6.7.2 n8n 工作流排程
|
||||||
|
|
||||||
|
- 由 n8n 內建排程節點管理
|
||||||
|
- 不與 crontab 衝突
|
||||||
|
|
||||||
|
### 6.8 故障排除
|
||||||
|
|
||||||
|
#### 6.8.1 常見問題
|
||||||
|
|
||||||
|
| 問題 | 原因 | 解決方案 |
|
||||||
|
|------|------|----------|
|
||||||
|
| n8n 版本警告 | 使用 Node 25.x | 確認 plist 使用 node@22 |
|
||||||
|
| Python 腳本找不到模組 | 未啟用 venv | 使用 venv/bin/python |
|
||||||
|
| 執行權限錯誤 | shebang 錯誤 | 確認 #!/opt/homebrew/bin/python3.11 |
|
||||||
|
| Port 被佔用 | 多個服務使用相同 port | 分配獨立 port |
|
||||||
|
|
||||||
|
#### 6.8.2 診斷命令
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 檢查 Python 版本
|
||||||
|
which python
|
||||||
|
/opt/homebrew/bin/python3.11 --version
|
||||||
|
|
||||||
|
# 檢查 Node.js 版本
|
||||||
|
/opt/homebrew/opt/node@22/bin/node --version
|
||||||
|
|
||||||
|
# 檢查 n8n 程序
|
||||||
|
ps aux | grep n8n
|
||||||
|
|
||||||
|
# 檢查 Python 程序
|
||||||
|
ps aux | grep python
|
||||||
|
|
||||||
|
# 檢查 Port 佔用
|
||||||
|
lsof -i :5678 # n8n
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.9 新增服務決策
|
||||||
|
|
||||||
|
```
|
||||||
|
新服務需要哪種執行環境?
|
||||||
|
│
|
||||||
|
├─ Python 腳本 ──▶ 使用專案 venv
|
||||||
|
│ (路徑: venv/bin/python)
|
||||||
|
│
|
||||||
|
├─ Node.js 工具 ──▶ 評估版本需求
|
||||||
|
│ │
|
||||||
|
│ ├─ 支援 Node 22 ──▶ 使用 node@22
|
||||||
|
│ │
|
||||||
|
│ └─ 需要其他版本 ──▶ 安裝新版本 (如 node@20)
|
||||||
|
│
|
||||||
|
└─ 現有服務依賴 ──▶ 根據現有服務配置
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.10 文件維護
|
||||||
|
|
||||||
|
當新增 Python 或 Node.js 服務時:
|
||||||
|
|
||||||
|
1. 更新本文檔的版本表格
|
||||||
|
2. 建立對應的監控腳本
|
||||||
|
3. 如需 launchd plist,建立並加入 `momentry_runtime/plist/`
|
||||||
|
4. 更新 `docs/NODEJS.md` 或 `docs/PYTHON.md`
|
||||||
|
|
||||||
|
### 5.2 進度回報
|
||||||
|
|
||||||
|
透過 stderr 回報進度,供 Rust 端解析:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Python 腳本
|
||||||
|
import sys
|
||||||
|
|
||||||
|
print(f"ASR_START", file=sys.stderr)
|
||||||
|
print(f"ASR_LANGUAGE:{detected_lang}", file=sys.stderr)
|
||||||
|
print(f"ASR_PROGRESS:{count}", file=sys.stderr)
|
||||||
|
print(f"ASR_COMPLETE:{total}", file=sys.stderr)
|
||||||
|
```
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// Rust 端解析
|
||||||
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||||
|
for line in stderr.lines() {
|
||||||
|
if line.starts_with("ASR_PROGRESS:") {
|
||||||
|
let count = line.trim_start_matches("ASR_PROGRESS:");
|
||||||
|
println!("[ASR] Processed {} segments...", count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 7. 測試策略
|
||||||
|
|
||||||
### 6.1 單元測試
|
### 6.1 單元測試
|
||||||
|
|
||||||
@@ -338,7 +618,7 @@ mod mocks {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## 7. 日誌與監控
|
## 8. 日誌與監控
|
||||||
|
|
||||||
### 7.1 日誌規範
|
### 7.1 日誌規範
|
||||||
|
|
||||||
@@ -377,7 +657,7 @@ fn init_logging() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## 8. 性能優化
|
## 9. 性能優化
|
||||||
|
|
||||||
### 8.1 避免拷貝
|
### 8.1 避免拷貝
|
||||||
|
|
||||||
@@ -413,7 +693,7 @@ let pool = SqlxPool::connect(&DATABASE_URL).await?;
|
|||||||
let db = PostgresDb::new(pool);
|
let db = PostgresDb::new(pool);
|
||||||
```
|
```
|
||||||
|
|
||||||
## 9. 安全考量
|
## 10. 安全考量
|
||||||
|
|
||||||
### 9.1 敏感資訊
|
### 9.1 敏感資訊
|
||||||
|
|
||||||
@@ -442,7 +722,7 @@ Command::new("ffprobe")
|
|||||||
.output();
|
.output();
|
||||||
```
|
```
|
||||||
|
|
||||||
## 10. 文件編寫
|
## 11. 文件編寫
|
||||||
|
|
||||||
### 10.1 結構體/函式文件
|
### 10.1 結構體/函式文件
|
||||||
|
|
||||||
@@ -487,7 +767,7 @@ pub struct VideoRecord {
|
|||||||
pub async fn get_video(&self, uuid: &str) -> Result<Option<VideoRecord>>;
|
pub async fn get_video(&self, uuid: &str) -> Result<Option<VideoRecord>>;
|
||||||
```
|
```
|
||||||
|
|
||||||
## 11. CLI 命令設計
|
## 12. CLI 命令設計
|
||||||
|
|
||||||
### 11.1 命令結構
|
### 11.1 命令結構
|
||||||
|
|
||||||
@@ -538,7 +818,7 @@ match &cli.command {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## 12. 依賴管理
|
## 13. 依賴管理
|
||||||
|
|
||||||
### 12.1 版本約束
|
### 12.1 版本約束
|
||||||
|
|
||||||
@@ -556,7 +836,7 @@ serde = "1.0" # 精確版本
|
|||||||
- 優先使用標準庫
|
- 優先使用標準庫
|
||||||
- 選擇維護良好的套件
|
- 選擇維護良好的套件
|
||||||
|
|
||||||
## 13. 建構與部署
|
## 14. 建構與部署
|
||||||
|
|
||||||
### 13.1 建構命令
|
### 13.1 建構命令
|
||||||
|
|
||||||
@@ -587,7 +867,7 @@ cargo check --all-features
|
|||||||
cargo test
|
cargo test
|
||||||
```
|
```
|
||||||
|
|
||||||
## 14. 版本控制
|
## 15. 版本控制
|
||||||
|
|
||||||
### 14.1 提交訊息規範
|
### 14.1 提交訊息規範
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user