1360 lines
37 KiB
Markdown
1360 lines
37 KiB
Markdown
# MarkBase開發指南
|
||
|
||
##專案概述
|
||
|
||
**MarkBase - Momentry Display Engine**
|
||
|
||
Rust Axum Web伺服器,提供 Markdown渲染與檔案樹管理功能。
|
||
|
||
-技術棧:Rust 1.92+, Axum 0.7, SQLite, pulldown-cmark
|
||
-目標平台:macOS(含音訊控制功能)
|
||
-資料庫:Per-user SQLite in `data/users/<user_id>.sqlite`
|
||
|
||
##核心指令
|
||
|
||
```bash
|
||
#建構與測試
|
||
cargo build #建構專案
|
||
cargo test #域行所有測試
|
||
cargo test test_insert #執行特定測試
|
||
cargo clippy #代碼品質檢查
|
||
|
||
#執行伺服器
|
||
cargo run -- display #啟動顯示伺服器(預設 port 11438)
|
||
cargo run -- display -p8080 #自訂 port
|
||
cargo run -- display README.md #顯示指定 Markdown檔案
|
||
|
||
#渲染工具
|
||
cargo run -- render <FILE> #渲染 Markdown(輸出到 stdout)
|
||
cargo run -- render <FILE> -o output.html #輸出到檔案
|
||
````
|
||
|
||
##架構概覽
|
||
|
||
###核心模組
|
||
|
||
|模組 |檔案 |功能 |
|
||
|------|------|------|
|
||
| CLI入口 | `main.rs` | clap指令解析 |
|
||
| Web伺服器 | `server.rs` | Axum REST API(18+路由) |
|
||
|檔案樹管理 | `filetree/mod.rs` | SQLite CRUD操作 |
|
||
| Markdown渲染 | `render.rs` | pulldown-cmark轉換 |
|
||
|音訊控制 | `audio.rs` | macOS音訊裝置管理 |
|
||
|指令隊列 | `command.rs` | WebSocket指令處理 |
|
||
|
||
###資料庫結構
|
||
|
||
-位置:`data/users/<user_id>.sqlite`
|
||
-表:`file_registry`, `file_nodes`, `file_locations`
|
||
-每個 user_id獨立資料庫
|
||
|
||
---
|
||
|
||
## File Tree核心說明(重點章節)
|
||
|
||
###架構設計
|
||
|
||
File Tree是 MarkBase的核心模組,提供檔案樹管理功能。
|
||
|
||
**核心結構:**
|
||
```rust
|
||
FileTree {
|
||
user_id: String, //用戶ID
|
||
nodes: Vec<FileNode>, //節點列表
|
||
}
|
||
````
|
||
|
||
**節點類型:**
|
||
- **Folder** -資料夾節點(可包含子節點)
|
||
- **File** -檔案節點(指向實體檔案)
|
||
|
||
###資料庫設計
|
||
|
||
**SQLite表結構:**
|
||
|
||
|表名 |功能 |
|
||
|------|------|
|
||
| file_registry |檔案註冊資訊 |
|
||
| file_nodes |檔案樹節點 |
|
||
| file_locations |檔案位置記錄 |
|
||
|
||
**節點欄位:**
|
||
```
|
||
node_id, label, aliases_json, file_uuid, sha256,
|
||
parent_id, children_json, node_type, icon, color,
|
||
bg_color, file_size, registered_at, created_at,
|
||
updated_at, sort_order
|
||
````
|
||
|
||
###公開API(13個函數)
|
||
|
||
|函數名 |功能 |檔案位置 |
|
||
|--------|------|----------|
|
||
| user_db_path | 取得DB路徑 | mod.rs:58 |
|
||
| init_user_db | 初始化DB | mod.rs:62 |
|
||
| open_user_db | 開啟DB | mod.rs:74 |
|
||
| load | 載入檔案樹 | mod.rs:79 |
|
||
| insert_node | 插入節點 | mod.rs:112 |
|
||
| update_node | 更新節點 | mod.rs:149 |
|
||
| update_node_alias | 更新別名 | mod.rs:187 |
|
||
| delete_node | 刪除節點 | mod.rs:214 |
|
||
| move_node | 移動節點 | mod.rs:220 |
|
||
| build_tree | 建立樹狀結構 | mod.rs:240 |
|
||
| new_folder | 建立資料夾節點 | node.rs:27 |
|
||
| new_file_node | 建立檔案節點 | node.rs:300 |
|
||
| add_location | 新增檔案位置 | mod.rs:346 |
|
||
|
||
### REST API(7個路由)
|
||
|
||
|路由 |方法 |功能 |server.rs行號 |
|
||
|------|------|------|--------------|
|
||
| `/api/v2/auth/login` | POST | 登入(返回token) | 1203 |
|
||
| `/api/v2/auth/logout` | POST | 登出(需Bearer token) | 1220 |
|
||
| `/api/v2/auth/verify` | GET | 验证token有效性 | 1238 |
|
||
| `/api/v2/tree/:user_id` | GET | 取得檔案樹(需認證) | 395 |
|
||
| `/api/v2/tree/:user_id` | DELETE | 刪除所有節點(需認證) | 64 |
|
||
| `/api/v2/tree/:user_id/node` | POST | 建立節點(需認證) | 62 |
|
||
| `/api/v2/tree/:user_id/node/:node_id` | PUT | 更新節點(需認證) | 63 |
|
||
| `/api/v2/tree/:user_id/node/:node_id` | DELETE | 刪除節點 | 63 |
|
||
| `/api/v2/tree/:user_id/node/:node_id/move` | PUT | 移動節點 | 71 |
|
||
| `/api/v2/tree/:user_id/node/:node_id/alias` | PATCH | 更新別名 | 72 |
|
||
| `/api/v2/tree/:user_id/restore` | POST | 從外部API恢復 | 65 |
|
||
|
||
**Query參數:**
|
||
- `mode` -顯示模式
|
||
|
||
**使用範例:**
|
||
```bash
|
||
#登入取得token
|
||
curl -X POST http://localhost:11438/api/v2/auth/login \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"username":"demo","password":"demo123"}'
|
||
#返回:{"token":"xxx","expires_at":"...","user_id":"demo"}
|
||
|
||
#使用token訪問檔案樹
|
||
curl http://localhost:11438/api/v2/tree/demo \
|
||
-H "Authorization: Bearer <TOKEN>"
|
||
```
|
||
|
||
**認證說明:**
|
||
- 所有 `/api/v2/tree/*` 和 `/api/v2/files/*` API 需要認證
|
||
- Token有效期:24小時
|
||
- 默認用戶:`demo` /密碼:`demo123`
|
||
````
|
||
---
|
||
##認證系統(Authentication)
|
||
|
||
###認證方式
|
||
|
||
**Token-BasedAuthentication:**
|
||
- UUID Token(簡單可靠)
|
||
- 24小時有效期
|
||
- Session管理(in-memory)
|
||
|
||
**APIEndpoints:**
|
||
|Endpoint |方法 |功能 |
|
||
|---------|------|------|
|
||
| `/api/v2/auth/login` | POST | 登入(返回token) |
|
||
| `/api/v2/auth/logout` | POST | 登出(需Bearer token) |
|
||
| `/api/v2/auth/verify` | GET | 验证token |
|
||
|
||
**使用流程:**
|
||
```
|
||
1.登入 →取得token
|
||
2.使用token訪問API(Authorization: Bearer <token>)
|
||
3.Token过期 →重新登入
|
||
```
|
||
|
||
###默認用戶
|
||
|
||
**測試用戶:**
|
||
- Username: `demo`
|
||
- Password: `demo123`
|
||
- UserID: `demo`
|
||
|
||
**密碼安全:**
|
||
- bcrypt加密(DEFAULT_COST)
|
||
- 密碼不以明文儲存
|
||
|
||
###認證範例
|
||
|
||
**登入:**
|
||
```bash
|
||
curl -X POST http://localhost:11438/api/v2/auth/login \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"username":"demo","password":"demo123"}'
|
||
```
|
||
|
||
**返回:**
|
||
```json
|
||
{
|
||
"token": "b2060c13-2a2d-4d5c-82e9-985bbdadbea2",
|
||
"expires_at": "2026-05-17T09:53:51Z",
|
||
"user_id": "demo"
|
||
}
|
||
```
|
||
|
||
**使用Token訪問:**
|
||
```bash
|
||
curl http://localhost:11438/api/v2/tree/demo \
|
||
-H "Authorization: Bearer b2060c13-2a2d-4d5c-82e9-985bbdadbea2"
|
||
```
|
||
|
||
**验证Token:**
|
||
```bash
|
||
curl http://localhost:11438/api/v2/auth/verify \
|
||
-H "Authorization: Bearer <TOKEN>"
|
||
```
|
||
|
||
**登出:**
|
||
```bash
|
||
curl -X POST http://localhost:11438/api/v2/auth/logout \
|
||
-H "Authorization: Bearer <TOKEN>"
|
||
```
|
||
|
||
###保護範圍
|
||
|
||
**需要認證的API:**
|
||
- `/api/v2/tree/*` -檔案樹管理
|
||
- `/api/v2/files/*` -檔案操作
|
||
- `/api/v2/upload/*` -檔案上傳
|
||
- `/api/v2/render/*` -檔案渲染
|
||
|
||
**公開API(無需認證):**
|
||
- `/` -根路徑
|
||
- `/api/v2/auth/*` -認證相關
|
||
- `/version` -版本信息
|
||
- `/api/v2/modes` -顯示模式
|
||
|
||
###擴展建議
|
||
|
||
**可擴展功能:**
|
||
1. JWT認證(已添加依賴,未啟用)
|
||
2. 用戶管理API(create_user已實現)
|
||
3.持久化Session(目前in-memory)
|
||
4. RBAC權限控制
|
||
|
||
---
|
||
|
||
### DisplayMode(顯示模式)
|
||
|
||
**顯示模式選項:**
|
||
|
||
|模式 |檔案 |用途 |
|
||
|------|------|------|
|
||
| tree | `modes/tree.rs` |樹狀顯示 |
|
||
| list | `modes/list.rs` |列表顯示 |
|
||
| grid_sm | `modes/grid_sm.rs` |小格狀顯示 |
|
||
| grid_lg | `modes/grid_lg.rs` |大格狀顯示 |
|
||
|
||
**DisplayMode trait定義(mode.rs:19):**
|
||
```rust
|
||
pub trait DisplayMode: Send + Sync {
|
||
fn name(&self) -> &'static str;
|
||
fn render(&self, tree: &FileTree) -> Value;
|
||
fn sort_options(&self) -> Vec<SortOption>;
|
||
fn filter_options(&self) -> Vec<FilterOption>;
|
||
}
|
||
````
|
||
|
||
###檔案轉換功能(convert.rs)
|
||
|
||
**支援格式轉換:**
|
||
|
||
|工具 |支援格式 |
|
||
|------|----------|
|
||
| textutil(macOS內建) | doc, docx, rtf |
|
||
| macOS工具 | pages, key, numbers |
|
||
| soffice/qlmanage | pptx, ppt, xlsx, xls, odt, epub |
|
||
|
||
**核心函數:**
|
||
- `is_doc_ext(ext)` - 檢查是否為文檔格式
|
||
- `get_cached_preview(file, ext)` - 生成緩存預覽
|
||
|
||
**緩存目錄:** `data/cache/`
|
||
|
||
###測試覆蓋現況
|
||
|
||
**已測試(7個):**
|
||
- ✅ init_and_load_empty_tree
|
||
- ✅ insert_and_load_node
|
||
- ✅ update_node
|
||
- ✅ delete_node
|
||
- ✅ move_node
|
||
- ✅ update_alias(zh_tw等多語言別名)
|
||
- ✅ build_tree(樹狀結構)
|
||
|
||
**待補測試:**
|
||
- ❌ convert.rs - 檔案轉換功能
|
||
- ❌ modes/*.rs - DisplayMode渲染
|
||
- ❌ API路由 - REST endpoint測試
|
||
|
||
###開發範例
|
||
|
||
**新增節點範例:**
|
||
```rust
|
||
//建立資料夾
|
||
let folder = FileTree::new_folder("Videos", None);
|
||
tree.insert_node(&conn, &folder)?;
|
||
|
||
//建立檔案節點
|
||
let (file_node, register_sql) = FileTree::new_file_node(
|
||
"demo.mp4",
|
||
"abc123def456...",
|
||
Some("sha256hash"),
|
||
"demo.mp4",
|
||
Some(1024000),
|
||
Some("video/mp4"),
|
||
None,
|
||
Some(folder.node_id),
|
||
);
|
||
tree.insert_node(&conn, &file_node)?;
|
||
````
|
||
|
||
**查詢範例:**
|
||
```rust
|
||
//載入檔案樹
|
||
let tree = FileTree::load(&conn, &user_id)?;
|
||
|
||
//建立樹狀結構(parent-child關係)
|
||
let roots = tree.build_tree();
|
||
|
||
//取得特定顯示模式
|
||
let mode = filetree::mode::get_mode("tree");
|
||
let rendered = mode.render(&tree);
|
||
````
|
||
|
||
---
|
||
|
||
## SFTPGo同步系統(Authentication Sync)
|
||
|
||
###系統架構
|
||
|
||
**同步流程:**
|
||
```
|
||
SFTPGo (PostgreSQL) → MarkBase (auth.sqlite)
|
||
users表 → sftpgo_users表
|
||
groups表 → sftpgo_groups表
|
||
users_groups_mapping表 → users_groups_mapping表
|
||
```
|
||
|
||
**同步策略:**
|
||
-啟動時同步(server.rs startup task)
|
||
-每小時自動同步(tokio interval task)
|
||
-手動同步API(/api/v2/admin/sync)
|
||
-失敗時使用緩存fallback
|
||
|
||
###數據庫結構
|
||
|
||
**auth.sqlite位置:** `data/auth.sqlite`
|
||
|
||
**表結構:**
|
||
|表名 |功能 |
|
||
|------|------|
|
||
| sftpgo_users |用戶信息(username, password_hash, status, permissions) |
|
||
| sftpgo_groups |群組信息(name, description) |
|
||
| users_groups_mapping |用戶-群組映射(username, group_name) |
|
||
| sync_log |同步日志(sync_type, sync_time, status) |
|
||
|
||
### PostgreSQL連接配置
|
||
|
||
**默認配置(pg_client.rs):**
|
||
```
|
||
host: 127.0.0.1
|
||
port: 5432
|
||
user: sftpgo
|
||
password: sftpgo_pass_2026
|
||
database: sftpgo
|
||
```
|
||
|
||
**環境變數配置(優先):**
|
||
```bash
|
||
export PG_HOST=127.0.0.1
|
||
export PG_PORT=5432
|
||
export PG_USER=sftpgo
|
||
export PG_PASSWORD=sftpgo_pass_2026
|
||
export PG_DATABASE=sftpgo
|
||
```
|
||
|
||
###同步API
|
||
|
||
**手動同步:**
|
||
```bash
|
||
curl -X POST http://localhost:11438/api/v2/admin/sync
|
||
```
|
||
|
||
**返回示例:**
|
||
```json
|
||
{
|
||
"users_synced": 3,
|
||
"groups_synced": 1,
|
||
"mappings_synced": 0,
|
||
"status": "success"
|
||
}
|
||
```
|
||
|
||
**同步狀態查詢:**
|
||
```bash
|
||
curl http://localhost:11438/api/v2/admin/sync/status
|
||
```
|
||
|
||
**返回示例:**
|
||
```json
|
||
{
|
||
"status": "ok",
|
||
"latest_sync": {
|
||
"sync_type": "full",
|
||
"sync_time": 1778927765,
|
||
"users_synced": 3,
|
||
"groups_synced": 1,
|
||
"mappings_synced": 0,
|
||
"status": "success"
|
||
}
|
||
}
|
||
```
|
||
|
||
###認證流程
|
||
|
||
**登入流程:**
|
||
```
|
||
1.客戶端發送登入請求(username, password)
|
||
2.服務器從auth.sqlite查詢用戶
|
||
3.bcrypt驗證密碼
|
||
4.生成UUID token(24小時有效)
|
||
5.返回token、expires_at、groups、permissions
|
||
```
|
||
|
||
**登入API:**
|
||
```bash
|
||
curl -X POST http://localhost:11438/api/v2/auth/login \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"username":"demo","password":"your_password"}'
|
||
```
|
||
|
||
**返回示例:**
|
||
```json
|
||
{
|
||
"token": "8d85c37d-8cc2-4633-a838-5400bb88dc6f",
|
||
"expires_at": "2026-05-17T10:39:05Z",
|
||
"user_id": "demo",
|
||
"groups": [],
|
||
"permissions": "{\"/*\": [\"*\"]}"
|
||
}
|
||
```
|
||
|
||
###測試用戶
|
||
|
||
**SFTPGo用戶(狀態=1):**
|
||
- warren(原始密碼hash:\$2a\$10\$TpGOufSlx...)
|
||
- momentry(原始密碼hash:\$2a\$10\$Yn/43aBY...)
|
||
- demo(原始密碼hash:\$2a\$10\$wCQC0wGRe...)
|
||
|
||
**測試密碼:**
|
||
為測試目的,可設置統一密碼:
|
||
```bash
|
||
# 在PostgreSQL中更新密碼為demo123
|
||
psql -h 127.0.0.1 -p 5432 -U sftpgo -d sftpgo -c "
|
||
UPDATE users SET password = '\$2b\$10\$ha5wU.mOi8fHLJCfun860u2cfVopa04jwe/q82IKOwqp5uG70qsH6'
|
||
WHERE username IN ('warren', 'momentry', 'demo');
|
||
"
|
||
|
||
# 重新同步
|
||
curl -X POST http://localhost:11438/api/v2/admin/sync
|
||
|
||
#測試登入
|
||
curl -X POST http://localhost:11438/api/v2/auth/login \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"username":"warren","password":"demo123"}'
|
||
```
|
||
|
||
###同步模組
|
||
|
||
**sync.rs:**
|
||
- `AuthDb` - auth.sqlite操作(get_user, get_user_groups, save_user)
|
||
- `SyncResult` -同步結果統計(users_synced, groups_synced, status)
|
||
- `PgUser, PgGroup, PgUserGroupMapping` - PostgreSQL數據結構
|
||
|
||
**pg_client.rs:**
|
||
- `PgClient` - PostgreSQL連接客戶端
|
||
- `SftpGoSync` -同步器(fetch_users, fetch_groups, full_sync)
|
||
|
||
**server.rs:**
|
||
- `/api/v2/admin/sync` -手動同步endpoint
|
||
- `/api/v2/admin/sync/status` -同步狀態endpoint
|
||
- startup sync task -啟動時同步
|
||
- hourly sync task -每小時同步(tokio::spawn)
|
||
|
||
###測試結果(2026-05-16)
|
||
|
||
**測試時間:**18:39
|
||
|
||
**測試狀態:** ✅ 全部成功
|
||
|
||
**測試項目:**
|
||
- ✅ PostgreSQL連接成功
|
||
- ✅ 手動同步API成功(3用戶, 1群組)
|
||
- ✅ 登入測試成功(demo/momentry/warren)
|
||
- ✅ Token驗證成功
|
||
- ✅ 保護API訪問成功
|
||
|
||
**密碼測試:**
|
||
使用統一密碼demo123測試,bcrypt驗證成功。
|
||
|
||
---
|
||
|
||
##測試執行
|
||
|
||
###執行測試
|
||
|
||
```bash
|
||
cargo test #域行所有測試
|
||
cargo test test_insert #執行特定測試
|
||
cargo test -- --nocapture #顯示詳細輸出
|
||
rm data/users/test_*.sqlite #清理暫存資料庫
|
||
````
|
||
|
||
###測試現況
|
||
|
||
|模組 |狀態 |說明 |
|
||
|------|------|------|
|
||
| filetree/mod.rs | ✅已測試 | 7個 CRUD測試 |
|
||
| filetree/convert.rs | ❌待補 | 檔案轉換測試 |
|
||
| filetree/modes/*.rs | ❌待補 | DisplayMode測試 |
|
||
| server.rs(API路由) | ❌待補 | API handler測試 |
|
||
| render.rs | ❌待補 | Markdown渲染測試 |
|
||
| audio.rs | ❌待補 | macOS音訊功能測試 |
|
||
|
||
###測試清理
|
||
|
||
測試會產生暫存資料庫:`data/users/test_*.sqlite`
|
||
|
||
階段性任務結束後應手動清除:
|
||
```bash
|
||
rm data/users/test_*.sqlite
|
||
````
|
||
|
||
---
|
||
|
||
##展示執行
|
||
|
||
###啟動伺服器
|
||
|
||
```bash
|
||
cargo run -- display #啟動(自動開啟瀏覽器)
|
||
cargo run -- render <file> #渲染 Markdown檔案
|
||
````
|
||
|
||
###Demo資料
|
||
|
||
- `data/users/demo.sqlite` - 50節點範例資料
|
||
- 5個 Folder節點
|
||
- 45個 File節點
|
||
- `data/cache/` -範例檔案
|
||
- 29ffd4c12ef6481da6bee7ae4c36a89f.jpg
|
||
- 2c62f90aacc542a9bcfa0c65b63be02a.txt
|
||
|
||
###Demo資料庫結構
|
||
|
||
```
|
||
Home(根資料夾)
|
||
├── Movies(子資料夾,包含影片檔案)
|
||
├── Marketing(子資料夾,包含行銷素材)
|
||
├── Cartoons(子資料夾,包含動畫檔案)
|
||
└── Other(子資料夾,包含其他檔案)
|
||
````
|
||
|
||
---
|
||
|
||
## macOS環境需求
|
||
|
||
###必要工具
|
||
|
||
- **SwitchAudioSource** -音訊裝置切換CLI
|
||
```bash
|
||
brew install switchaudio-source
|
||
SwitchAudioSource -a #列出所有音訊裝置
|
||
````
|
||
|
||
### macOS限定功能
|
||
|
||
|功能 |依賴 |說明 |
|
||
|------|------|------|
|
||
|音訊裝置切換 | SwitchAudioSource | `/devices` API |
|
||
|音量控制 | osascript | `/volume` API |
|
||
|語音測試 | say命令 | `/command` API(test_voice) |
|
||
|文檔轉換 | textutil | convert.rs(doc/rtf轉換) |
|
||
|
||
---
|
||
|
||
## CI/CD配置(Gitea Actions)
|
||
|
||
### Access Token 配置
|
||
|
||
**Token資訊:**
|
||
- **Token名稱:** OpenCode_M4Mini
|
||
- **建立日期:** 2026-05-16
|
||
- **擁有者:** warren (Warren Lo)
|
||
- **權限範圍:** repo (完整倉庫權限)
|
||
- **用途:** CI/CD部署、倉庫管理、自動化操作
|
||
|
||
**Token值:** `c5e025496ebc3c7408a971d64a33bd56aac9186c`
|
||
|
||
**使用方式:**
|
||
```bash
|
||
# API認證
|
||
curl -H "Authorization: token c5e025496ebc3c7408a971d64a33bd56aac9186c" \
|
||
https://gitea.momentry.ddns.net/api/v1/user
|
||
|
||
# Git推送(需配置遠端)
|
||
git remote set-url origin https://oauth2:c5e025496ebc3c7408a971d64a33bd56aac9186c@gitea.momentry.ddns.net/warren/markbase.git
|
||
```
|
||
|
||
**安全提醒:**
|
||
- ⚠️ 此Token僅用於本機開發環境
|
||
- ⚠️ 請勿提交到公開倉庫
|
||
- ⚠️ 定期更換Token(建議每90天)
|
||
- ⚠️ 如需撤銷:Gitea → Settings → Applications → Access Tokens → Delete
|
||
|
||
###環境資訊
|
||
|
||
- **Gitea Server**: https://gitea.momentry.ddns.net
|
||
- **Gitea版本**: 1.25.3(支援 Actions)
|
||
- **Runner**: 本機Mac(實機測試)
|
||
- **Workflow**: `.gitea/workflows/*.yml`
|
||
|
||
### Runner配置步驟
|
||
|
||
**1. 取得 Runner Token**
|
||
- 登入 Gitea: https://gitea.momentry.ddns.net
|
||
- Settings → Actions → Runners →建立新 Runner
|
||
|
||
**2. 下載並安裝 Runner**
|
||
```bash
|
||
# macOS ARM版本
|
||
wget https://dl.gitea.com/act_runner/latest/act_runner-darwin-arm64
|
||
chmod +x act_runner-darwin-arm64
|
||
sudo mv act_runner-darwin-arm64 /usr/local/bin/act_runner
|
||
````
|
||
|
||
**3. 註冊 Runner**
|
||
```bash
|
||
act_runner register --instance https://gitea.momentry.ddns.net --token <YOUR_TOKEN>
|
||
````
|
||
|
||
**4.啟動 Runner**
|
||
```bash
|
||
act_runner daemon
|
||
````
|
||
|
||
###Workflow範例
|
||
|
||
```yaml
|
||
# .gitea/workflows/test.yml
|
||
name: Test
|
||
on: [push, pull_request]
|
||
|
||
jobs:
|
||
test:
|
||
runs-on: macos-latest
|
||
steps:
|
||
- uses: actions/checkout@v3
|
||
|
||
- name: Setup Rust
|
||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||
|
||
- name: Install SwitchAudioSource
|
||
run: brew install switchaudio-source
|
||
|
||
- name: Run tests
|
||
run: cargo test --all
|
||
|
||
- name: Run clippy
|
||
run: cargo clippy --all-targets --all-features -- -D warnings
|
||
|
||
- name: Check formatting
|
||
run: cargo fmt -- --check
|
||
|
||
- name: Clean test databases
|
||
run: rm -f data/users/test_*.sqlite
|
||
````
|
||
|
||
---
|
||
|
||
##開發環境設定
|
||
|
||
###開發環境API Key
|
||
|
||
`server.rs:192`包含開發環境 API key:
|
||
```rust
|
||
let api_key = "muser_68600856036340bcafc01930eb4bd839_1774418104_97221b69";
|
||
let api_url = "http://localhost:3002/api/v1/files";
|
||
````
|
||
|
||
用途:`restore_tree`功能從外部 API恢復檔案樹。
|
||
|
||
**改進建議:**
|
||
-應改用環境變數配置
|
||
- 建立 `.env.example`範例
|
||
|
||
###環境變數配置(待實作)
|
||
|
||
```bash
|
||
# .env(未來配置)
|
||
RESTORE_API_KEY=muser_your_api_key_here
|
||
RESTORE_API_URL=http://localhost:3002
|
||
SERVER_PORT=11438
|
||
DB_DIR=data/users
|
||
````
|
||
|
||
---
|
||
|
||
##代碼風格
|
||
|
||
###Rust標準工具
|
||
|
||
```bash
|
||
cargo fmt #代碼格式化
|
||
cargo clippy #代碼品質檢查
|
||
````
|
||
|
||
**現有clippy警告:**
|
||
- server.rs:609 -未使用變數 `state`
|
||
- server.rs:1020 -未使用變數 `pg_url`
|
||
|
||
---
|
||
|
||
##專案結構
|
||
|
||
```
|
||
markbase/
|
||
├── src/
|
||
│ ├── main.rs # CLI入口
|
||
│ ├── lib.rs #模組宣告
|
||
│ ├── server.rs # Web伺服器(18+路由)
|
||
│ ├── render.rs # Markdown渲染
|
||
│ ├── audio.rs # macOS音訊
|
||
│ ├── command.rs #指令隊列
|
||
│ ├── page.html # HTML模板
|
||
│ └── filetree/
|
||
│ ├── mod.rs #檔案樹核心(553行)
|
||
│ ├── convert.rs #檔案轉換(253行)
|
||
│ ├── mode.rs # DisplayMode trait(43行)
|
||
│ ├── node.rs #節點定義(82行)
|
||
│ └── modes/
|
||
│ ├── tree.rs #樹狀模式(57行)
|
||
│ ├── list.rs #列表模式(87行)
|
||
│ ├── grid_sm.rs #小格狀模式(72行)
|
||
│ ├── grid_lg.rs #大格狀模式(83行)
|
||
│ └── mod.rs #模式匯出(4行)
|
||
├── data/
|
||
│ ├── users/ # SQLite資料庫
|
||
│ │ ├── demo.sqlite # Demo資料(50節點)
|
||
│ │ └── test_*.sqlite #測試暫存(已清理)
|
||
│ └── cache/ #檔案緩存
|
||
│ ├── *.jpg #圖片緩存
|
||
│ └── *.txt #文本緩存
|
||
├── tests/ #整合測試(待建立)
|
||
├── examples/ #範例檔案(待建立)
|
||
├── .gitea/
|
||
│ └ workflows/
|
||
│ ├── test.yml #測試workflow(待建立)
|
||
│ ├── build.yml #建構workflow(待建立)
|
||
│ └── release.yml #發布workflow(待建立)
|
||
├── Cargo.toml # Rust配置
|
||
├── Cargo.lock #依賴鎖定
|
||
└── AGENTS.md # 本文件
|
||
````
|
||
|
||
---
|
||
|
||
##常見問題
|
||
|
||
###測試暫存檔清理
|
||
|
||
```bash
|
||
rm data/users/test_*.sqlite
|
||
````
|
||
|
||
###音訊功能無效
|
||
|
||
確認 `SwitchAudioSource`已安裝:
|
||
```bash
|
||
brew install switchaudio-source
|
||
SwitchAudioSource -a #列出音訊裝置
|
||
````
|
||
|
||
###File Tree API測試
|
||
|
||
```bash
|
||
curl http://localhost:11438/api/v2/tree/demo
|
||
curl http://localhost:11438/api/v2/tree/demo?mode=tree
|
||
````
|
||
|
||
###CI/CD Runner連接失敗
|
||
|
||
確認 Runner已配置並啟動:
|
||
```bash
|
||
act_runner list #查看 Runner狀態
|
||
act_runner daemon #啟動 Runner
|
||
```
|
||
|
||
###CI/CD日志查看方式
|
||
|
||
**方法1:通過 Gitea Web UI查看(推薦)**
|
||
```
|
||
https://gitea.momentry.ddns.net/warren/markbase/actions
|
||
```
|
||
|
||
**方法2:通過 API獲取詳細日志**
|
||
|
||
**步驟:**
|
||
1. **獲取所有 Actions Runs**
|
||
```bash
|
||
curl -H "Authorization: token c5e025496ebc3c7408a971d64a33bd56aac9186c" \
|
||
https://gitea.momentry.ddns.net/api/v1/repos/warren/markbase/actions/runs | jq '.workflow_runs[] | {id, status, conclusion}'
|
||
```
|
||
|
||
2. **獲取特定 Run的所有 Jobs**
|
||
```bash
|
||
curl -H "Authorization: token c5e025496ebc3c7408a971d64a33bd56aac9186c" \
|
||
https://gitea.momentry.ddns.net/api/v1/repos/warren/markbase/actions/runs/<RUN_ID>/jobs | jq '.jobs[] | {id, name, status, conclusion}'
|
||
```
|
||
|
||
3. **獲取 Job詳細日志**
|
||
```bash
|
||
curl -H "Authorization: token c5e025496ebc3c7408a971d64a33bd56aac9186c" \
|
||
https://gitea.momentry.ddns.net/api/v1/repos/warren/markbase/actions/jobs/<JOB_ID>/logs
|
||
```
|
||
|
||
**範例:查看 Run ID 6的 test job日志**
|
||
```bash
|
||
# Step 1: 獲取 jobs列表
|
||
curl -s -H "Authorization: token c5e025496ebc3c7408a971d64a33bd56aac9186c" \
|
||
https://gitea.momentry.ddns.net/api/v1/repos/warren/markbase/actions/runs/6/jobs | jq '.jobs[] | {id, name}'
|
||
|
||
# Step 2:獲取 job 11(test job)的完整日志
|
||
curl -s -H "Authorization: token c5e025496ebc3c7408a971d64a33bd56aac9186c" \
|
||
https://gitea.momentry.ddns.net/api/v1/repos/warren/markbase/actions/jobs/11/logs
|
||
```
|
||
|
||
**日志格式:**
|
||
- 每行以時間戳開頭:`2026-05-16T08:26:07.5859940Z`
|
||
- 包含完整執行過程、命令輸出、錯誤信息
|
||
- 錯誤行通常包含 `##[error]`標記
|
||
|
||
**常見錯誤診斷:**
|
||
- `conditional binary operator expected` → bash腳本語法問題
|
||
- `Process completed with exit code 2` →腳本執行失敗
|
||
- `Unable to pull refs/heads/v3` → Git clone問題(通常可忽略)`
|
||
|
||
---
|
||
|
||
##部署狀況記錄(2026-05-16)
|
||
|
||
###已完成部署
|
||
|
||
**倉庫建立:**
|
||
- ✅ warren/markbase 倉庫已建立(ID: 27)
|
||
- ✅ URL: https://gitea.momentry.ddns.net/warren/markbase
|
||
- ✅ 代碼已推送(4 commits)
|
||
|
||
**Runner配置:**
|
||
- ✅ Runner已註冊(ID: 2)
|
||
- ✅ Runner名稱: accusys-Mac-mini-M4-2.local
|
||
- ✅ Runner標籤: macos-latest:host, macos-arm64:host
|
||
- ✅ Runner進程運行中(PID: 90905)
|
||
|
||
**Actions狀態:**
|
||
- ✅ Actions已觸發並執行
|
||
- ✅ Run ID 7: 成功(test + build jobs均通過) ← 最新
|
||
- ⚠️ Run ID 1-6: 失敗(Setup Rust bash兼容性問題)
|
||
- ✅ 本地測試全部通過(62 tests)
|
||
- ✅ Clippy檢查已通過
|
||
- ✅ 格式檢查已通過
|
||
|
||
###CI問題已解決(2026-05-16)
|
||
|
||
**問題根本原因:**
|
||
- GitHub Action(actions-rust-lang/setup-rust-toolchain@v1)與Gitea Runner bash環境不兼容
|
||
- 錯誤:`conditional binary operator expected`(line 2)
|
||
|
||
**解決方案:**
|
||
- 替換為原生rustup安裝:`curl | sh.rustup.rs`
|
||
- 在所有cargo命令前添加:`source $HOME/.cargo/env`
|
||
|
||
**結果:**
|
||
- ✅ Run ID 7: 成功(5分22秒,正常執行)
|
||
- ✅ test job: success
|
||
- ✅ build job: success
|
||
- ✅ CI/CD完全正常運行
|
||
|
||
**Commits記錄:**
|
||
- 87a3eea: 記錄CI日志獲取方式和問題診斷
|
||
- 34b6839: 替換GitHub Action為原生rustup安裝 ←修復提交
|
||
|
||
---
|
||
|
||
##部署測試經驗(2026-05-16)
|
||
|
||
###核心方法論
|
||
|
||
**CI日志獲取方法:**
|
||
```bash
|
||
#1.獲取 Run列表
|
||
curl -H "Authorization: token <TOKEN>" \
|
||
<GITEA_URL>/api/v1/repos/<OWNER>/<REPO>/actions/runs
|
||
|
||
#2.獲取 Job ID
|
||
curl -H "Authorization: token <TOKEN>" \
|
||
<GITEA_URL>/api/v1/repos/<OWNER>/<REPO>/actions/runs/<RUN_ID>/jobs
|
||
|
||
#3.獲取 Job日志
|
||
curl -H "Authorization: token <TOKEN>" \
|
||
<GITEA_URL>/api/v1/repos/<OWNER>/<REPO>/actions/jobs/<JOB_ID>/logs
|
||
```
|
||
|
||
**問題診斷思路:**
|
||
```
|
||
觀察現象 →獲取日志 →定位錯誤 →分析原因 →設計方案 →實施修復 →验证結果
|
||
```
|
||
|
||
**關鍵認知:**
|
||
- GitHub Actions ≠Gitea Runner環境(不完全兼容)
|
||
- 原生工具安裝 >Action依賴(更穩定可靠)
|
||
- 環境變數載入是必要步驟(`source $HOME/.cargo/env`)
|
||
|
||
**測試結果:**
|
||
-失敗→成功迭代:6次失敗 →1次成功
|
||
-執行時間對比:5秒(失敗)→5分22秒(成功)
|
||
-修復方案:原生rustup安裝替代GitHub Action
|
||
|
||
---
|
||
|
||
**最後更新:2026-05-16**
|
||
**版本:1.4(部署測試經驗版)**
|
||
---
|
||
|
||
## 配置系统
|
||
|
||
### 配置文件位置
|
||
|
||
**默认位置:** `config/markbase.toml`
|
||
|
||
**创建配置文件:**
|
||
```bash
|
||
cargo run -- config init # 创建默认配置文件
|
||
cargo run -- config init --force # 强制覆盖现有配置
|
||
```
|
||
|
||
### 配置参数说明
|
||
|
||
#### Server配置
|
||
- **host**: 服务器监听地址(默认:127.0.0.1)
|
||
- **port**: 服务器端口(默认:11438,范围:>=1024)
|
||
- **log_level**: 日志级别
|
||
- **auth_db_path**: 认证数据库路径(默认:data/auth.sqlite)
|
||
- **users_db_dir**: 用户数据库目录(默认:data/users)
|
||
|
||
#### PostgreSQL配置
|
||
- **host**: PostgreSQL服务器地址(默认:127.0.0.1)
|
||
- **port**: PostgreSQL端口(默认:5432)
|
||
- **user**: PostgreSQL用户名(默认:sftpgo)
|
||
- **password**: PostgreSQL密码(默认:sftpgo_pass_2026)
|
||
- **database**: PostgreSQL数据库(默认:sftpgo)
|
||
- **connection_pool_size**: 连接池大小(默认:5)
|
||
|
||
#### Authentication配置
|
||
- **bcrypt_cost**: bcrypt加密强度(默认:10,范围:4-31)
|
||
- **token_validity_hours**: Token有效期(默认:24小时)
|
||
- **session_storage**: Session存储方式(默认:memory)
|
||
- **max_sessions_per_user**: 每用户最大Session数(默认:5)
|
||
- **default_user**: 默认用户(默认:demo)
|
||
- **default_password**: 默认密码(默认:demo123)
|
||
|
||
#### Test配置
|
||
- **users**: 测试用户列表(默认:["warren", "momentry", "demo"])
|
||
- **password**: 测试统一密码(默认:demo123)
|
||
- **login_test_iterations**: Login性能测试迭代次数(默认:10)
|
||
- **verify_test_iterations**: Token验证测试迭代次数(默认:100)
|
||
- **api_test_iterations**: Protected API测试迭代次数(默认:50)
|
||
- **performance_report**: 是否生成性能报告(默认:true)
|
||
- **output_format**: 输出格式(默认:markdown)
|
||
|
||
#### Logging配置
|
||
- **level**: 日志级别(默认:info)
|
||
- **file_path**: 日志文件路径(默认:logs/markbase.log)
|
||
- **console_output**: 是否输出到控制台(默认:true)
|
||
- **structured_logging**: 是否使用结构化日志(默认:false)
|
||
|
||
### CLI Config命令
|
||
|
||
**查看配置:**
|
||
```bash
|
||
cargo run -- config show # 显示所有配置
|
||
cargo run -- config show --section server # 显示server配置
|
||
cargo run -- config show --section postgresql
|
||
cargo run -- config show --section authentication
|
||
```
|
||
|
||
**编辑配置:**
|
||
```bash
|
||
cargo run -- config edit --key server.port --value 8080
|
||
cargo run -- config edit --key postgresql.password --value new_pass
|
||
cargo run -- config edit --key authentication.token_validity_hours --value 48
|
||
```
|
||
|
||
**验证配置:**
|
||
```bash
|
||
cargo run -- config validate
|
||
```
|
||
|
||
### UI Settings面板
|
||
|
||
**访问方式:**
|
||
1. 打开浏览器访问 http://localhost:11438/
|
||
2. 点击底部栏⚙️Settings按钮
|
||
3. Settings面板将从顶部滑入
|
||
|
||
**功能:**
|
||
- **查看配置**:显示所有5个配置section(server, postgresql, authentication, test, logging)
|
||
- **编辑配置**:点击每个参数旁的Edit按钮,修改值后Save保存
|
||
- **验证配置**:点击Validate按钮验证配置有效性
|
||
- **Toast提示**:操作成功/失败显示提示信息
|
||
|
||
**API端点:**
|
||
|端点 |方法 |功能 |
|
||
|------|------|------|
|
||
| `/api/v2/config` | GET | 获取完整配置JSON |
|
||
| `/api/v2/config/edit` | POST | 编辑配置参数 |
|
||
| `/api/v2/config/validate` | GET | 验证配置有效性 |
|
||
|
||
**编辑示例:**
|
||
```bash
|
||
# 使用API修改配置
|
||
curl -X POST "http://localhost:11438/api/v2/config/edit?key=server.port&value=8080"
|
||
# 返回:{"ok":true}
|
||
|
||
# 验证配置
|
||
curl http://localhost:11438/api/v2/config/validate
|
||
# 返回:{"ok":true}
|
||
```
|
||
|
||
### 配置优先级
|
||
|
||
默认值 → 配置文件 → 环境变量 → CLI参数
|
||
|
||
**环境变量命名:**
|
||
- Server: `MB_HOST`, `MB_PORT`, `MB_LOG_LEVEL`
|
||
- PostgreSQL: `PG_HOST`, `PG_PORT`, `PG_USER`, `PG_PASSWORD`
|
||
- Authentication: `MB_BCRYPT_COST`, `MB_TOKEN_VALIDITY_HOURS`
|
||
|
||
---
|
||
|
||
## FUSE Virtual File System(2026-05-17新增)
|
||
|
||
### 功能概述
|
||
|
||
**虚拟文件系统挂载:**
|
||
- FUSE-T技术(Kext-less设计)
|
||
- Backend选择:NFSv4(稳定)或FSKit(macOS 26+,最快)
|
||
- 支持多用户并发挂载(10 users)
|
||
- 性能目标:600MB/s sustained write per user
|
||
|
||
### 设计文档
|
||
|
||
**架构概览:**
|
||
```
|
||
MarkBase FUSE System
|
||
├── src/fuse/mod.rs # FUSE核心模組
|
||
│ ├── BackendType # NFSv4/FSKit选择
|
||
│ ├── select_backend() # 自动检测backend
|
||
│ └── mount_hello_fs() # POC placeholder
|
||
├── docs/FUSE_DESIGN.md # 完整设计文档
|
||
└ docs/FUSE_POC_TEST.md # POC测试计划
|
||
```
|
||
|
||
**Backend选择逻辑:**
|
||
- macOS 26+:FSKit(native,direct path,minimal overhead)
|
||
- macOS <26:NFSv4(stable,TCP/IP overhead ~5-10%)
|
||
|
||
### CLI命令
|
||
|
||
**POC测试命令:**
|
||
```bash
|
||
# 检测backend
|
||
cargo run -- fuse detect-backend
|
||
# 输出:macOS 26.4.1 → Recommended: fskit
|
||
|
||
# POC placeholder mount
|
||
cargo run -- fuse poc --dir /tmp/fuse_test --backend auto
|
||
cargo run -- fuse poc --backend fskit # 手動指定 FSKit
|
||
cargo run -- fuse poc --backend nfs # 手動指定 NFSv4
|
||
```
|
||
|
||
**未来完整命令(Phase 2+):**
|
||
```bash
|
||
# 单user挂载
|
||
cargo run -- fuse --mount --user warren --dir /Volumes/MarkBase_warren
|
||
|
||
# 多user并发挂载
|
||
cargo run -- fuse --mount --all --dir /Volumes/
|
||
|
||
# 卸載
|
||
cargo run -- fuse --unmount --dir /Volumes/MarkBase_warren
|
||
cargo run -- fuse --unmount --all
|
||
```
|
||
|
||
### POC测试结果(2026-05-17)
|
||
|
||
**测试环境:**
|
||
- 硬體:M4 Mac mini, 16GB RAM, NVMe 2TB
|
||
- OS:macOS 26.4.1
|
||
- Backend:FSKit(自动检测)
|
||
|
||
**测试項目(7項全通過):**
|
||
- ✅ Backend detection(macOS 26.4.1 → FSKit)
|
||
- ✅ Auto backend selection(FSKit)
|
||
- ✅ Manual backend selection(FSKit/NFSv4)
|
||
- ✅ Error handling(invalid backend)
|
||
- ✅ Compilation check
|
||
- ✅ Unit tests(7 passed)
|
||
- ✅ CLI commands functional
|
||
|
||
**Unit Tests结果:**
|
||
```
|
||
running 7 tests
|
||
test fuse::backend::tests::test_backend_support ... ok
|
||
test fuse::backend::tests::test_backend_type_name ... ok
|
||
test fuse::backend::tests::test_manual_backend_selection ... ok
|
||
test fuse::poc_hello::tests::test_hello_fs_creation ... ok
|
||
test fuse::backend::tests::test_select_backend_macos_25 ... ok
|
||
test fuse::poc_hello::tests::test_mount_placeholder ... ok
|
||
test fuse::backend::tests::test_select_backend_macos_26 ... ok
|
||
test result: ok. 7 passed; 0 failed; 0 ignored
|
||
```
|
||
|
||
### FUSE-T vs macFUSE比較
|
||
|
||
|特性 |FUSE-T |macFUSE |
|
||
|------|--------|---------|
|
||
|Kernel Design |Kext-less(userspace)|Kernel Extension + FSKit |
|
||
|Backend Protocol |NFSv4 / SMB3 / FSKit |Direct kernel FUSE API |
|
||
|安装难度 |简单(brew install)|需System Settings設定 |
|
||
|稳定性 |穩定(userspace server)|可能kernel crash |
|
||
|授權 |免費個人,商業需授權 |開源(BSD)|
|
||
|macOS支援 |全版本 |macOS 12+ |
|
||
|App Store |可嵌入 |需特殊處理 |
|
||
|效能(FSKit) |~600-700 MB/s |~650-750 MB/s |
|
||
|
||
**推薦:FUSE-T**
|
||
- 稳定性优先(避免kernel panic)
|
||
- 部署友善(无需Security Settings)
|
||
- macOS 26支援FSKit backend(与macFUSE相同效能)
|
||
|
||
### 效能目标
|
||
|
||
|Metric |Target |Measurement Method |
|
||
|--------|--------|-------------------|
|
||
|Write throughput |>=600MB/s |AJA System Test 4K ProRes 4444 |
|
||
|Read throughput |>=800MB/s |AJA System Test 4K ProRes 422 HQ |
|
||
|Mount latency(single) |<100ms |Timing measurement |
|
||
|Mount latency(10 users) |<2s |Parallel mount timing |
|
||
|Concurrent writes |10 × 600MB/s |AJA concurrent test |
|
||
|Uptime stability |24h no crash |Stability test |
|
||
|Cache hit rate |>=90% |Cache statistics |
|
||
|
||
### 实作阶段
|
||
|
||
**Phase 1:POC验证(已完成 Day 1)**
|
||
- ✅ 建立fuse module结构
|
||
- ✅ Backend detection implementation
|
||
- ✅ CLI commands functional
|
||
- ✅ Unit tests pass(7 tests)
|
||
- ⏳ FUSE-T安装(需手动sudo)
|
||
- ⏳ AJA System Test下载(需手动)
|
||
|
||
**Phase 2:SQLite-backed FUSE(Day 3-5)**
|
||
- ❌ MarkBaseFs implementation
|
||
- ❌ FUSE operations(getattr, read, write)
|
||
- ❌ warren user test(12659 nodes)
|
||
- ❌ LRU caching
|
||
|
||
**Phase 3:Multi-user Concurrent(Day 6-8)**
|
||
- ❌ MountManager implementation
|
||
- ❌ 10 user parallel mount
|
||
- ❌ AJA concurrent write test
|
||
- ❌ 24h stability test
|
||
|
||
**Phase 4:Performance Optimization(Day 9-12)**
|
||
- ❌ Write buffering(64KB chunks)
|
||
- ❌ FSKit backend optimization
|
||
- ❌ 600MB/s validation
|
||
- ❌ Final documentation
|
||
|
||
### 手动安装步骤
|
||
|
||
**FUSE-T安装:**
|
||
```bash
|
||
# 检查下载的PKG
|
||
ls -lh ~/Downloads/fuse-t-1.2.6.pkg # 23MB
|
||
|
||
# 安装(需要sudo密码)
|
||
sudo installer -pkg ~/Downloads/fuse-t-1.2.6.pkg -target /
|
||
|
||
# 验证安装
|
||
ls -la /usr/local/bin/fuse-t
|
||
fuse-t --version # Expected: 1.2.6
|
||
```
|
||
|
||
**AJA System Test安装:**
|
||
```bash
|
||
# 手动下载(浏览器访问)
|
||
https://www.aja.com/en/products/aja-system-test
|
||
|
||
# 安装DMG
|
||
hdiutil attach ~/Downloads/AJA_System_Test.dmg
|
||
cp -R /Volumes/AJA\ System\ Test/*.app /Applications/
|
||
hdiutil detach /Volumes/AJA\ System\ Test
|
||
```
|
||
|
||
### 相关文档
|
||
|
||
|文档 |位置 |说明 |
|
||
|------|------|------|
|
||
|FUSE_DESIGN.md |docs/ |完整设计文档(架构、backend、性能)|
|
||
|FUSE_POC_TEST.md |docs/ |POC测试计划(7项测试)|
|
||
|FUSE_POC_REPORT.md |docs/ |POC测试报告(结果、下一步)|
|
||
|fuse_poc_test.sh |tests/ |自动化测试脚本 |
|
||
|
||
---
|
||
|
||
**最后更新:** 2026-05-17 10:20
|
||
**版本:** 1.8(FUSE Virtual File System版)
|
||
---
|
||
|
||
## File Scan System(2026-05-17新增)
|
||
|
||
### 功能概述
|
||
|
||
**异步导入系统:**
|
||
- 快速导入(skip_hash=true):立即显示文件树
|
||
- 后台hash:异步计算SHA256,不影响前端使用
|
||
|
||
### CLI命令
|
||
|
||
**scan命令:**
|
||
```bash
|
||
# 快速导入(默认skip_hash=true)
|
||
cargo run -- scan --user warren --dir /Users/accusys/momentry/var/sftpgo/data/warren
|
||
|
||
# 导入并计算hash(skip_hash=false)
|
||
cargo run -- scan --user warren --dir <path> --skip-hash false --threads 4
|
||
|
||
# 参数说明:
|
||
--user <USER> 用户ID
|
||
--dir <DIR> 扫描目录
|
||
--batch <BATCH> 批量插入大小(默认:100)
|
||
--skip-hash <BOOL> 跳过hash计算(默认:true)
|
||
--threads <THREADS> hash计算线程数(默认:4)
|
||
````
|
||
|
||
**hash命令:**
|
||
```bash
|
||
# 后台计算hash
|
||
cargo run -- hash --user warren --threads 4
|
||
|
||
# 参数说明:
|
||
--user <USER> 用户ID
|
||
--threads <THREADS> 并行线程数(默认:4)
|
||
````
|
||
|
||
### 效能测试结果(2026-05-17)
|
||
|
||
**测试配置:**
|
||
- 文件总数:11857 files + 801 folders = 12658 nodes
|
||
- 目录深度:多层子目录(Accusys/Accusys_FAE/VolPack_ME5012...)
|
||
- CPU线程:4 threads (M4 Mac mini)
|
||
|
||
**第一阶段:快速导入(skip_hash=true)**
|
||
- 目录扫描:0.10s
|
||
- ID生成:0.57s(主要瓶颈)
|
||
- 数据库插入:0.21s
|
||
- 总时间:0.89s
|
||
- 速度:14243 nodes/sec
|
||
|
||
**第二阶段:SHA256计算(4 threads)**
|
||
- 文件数:11857
|
||
- 总时间:417.58s
|
||
- 速度:28 files/sec
|
||
|
||
**效能瓶颈分析:**
|
||
1. ID生成(64%)- SHA256计算UUID耗时
|
||
2. 数据库插入(24%)- 批量插入优化
|
||
3. 目录扫描(11%)- fast, no bottleneck
|
||
4. Hash计算 - IO瓶颈(多线程未提速)
|
||
|
||
### 设计决策
|
||
|
||
**UUID生成策略:**
|
||
- 算法:SHA256(path|filename|mac|mtime).chars().take(32)
|
||
- 特性:确定性UUID(同一文件 = 同一UUID)
|
||
- 优势:无需外部API,支持增量导入
|
||
|
||
**路径存储方案:**
|
||
- 存储位置:aliases.json(临时方案)
|
||
- 格式:`{"path": "/full/path/to/file"}`
|
||
- 原因:file_nodes表无path字段
|
||
- 改进:未来添加file_locations表填充
|
||
|
||
**异步hash设计:**
|
||
- 导入优先:用户立即查看文件树
|
||
- hash后台:不影响前端使用
|
||
- 多线程:并行计算(IO瓶颈限制)
|
||
- 增量:只计算缺失hash的文件
|
||
|
||
### 数据库结构(warren.sqlite)
|
||
|
||
**节点统计:**
|
||
- Folders: 801
|
||
- Files: 11857
|
||
- Total: 12658
|
||
|
||
**示例节点:**
|
||
```
|
||
node_id: 8b1ede3cd6970f02fa85b8e34b682caf
|
||
label: Test_Plan_ME5.docx
|
||
aliases_json: {"path":"/Users/accusys/.../Test_Plan_ME5.docx"}
|
||
sha256: 355a063b697a812742fae2a021cdda5c
|
||
node_type: file
|
||
parent_id: (folder UUID)
|
||
````
|
||
|
||
### 使用流程
|
||
|
||
**完整导入流程:**
|
||
```
|
||
1. cargo run -- scan --user warren --dir <path> # 快速导入(0.89s)
|
||
2. cargo run -- hash --user warren --threads 4 # 后台hash(417s)
|
||
3. 查看文件树:http://localhost:11438/ → File Tree → Login
|
||
````
|
||
|
||
**增量导入流程:**
|
||
```
|
||
1. cargo run -- scan --user warren --dir <path> # 导入新文件
|
||
2. cargo run -- hash --user warren # 计算新hash(只计算缺失的)
|
||
````
|
||
|
||
### 相关文件
|
||
|
||
|文件 |功能 |
|
||
|------|------|
|
||
| src/scan.rs | 扫描导入 + hash计算(499行)|
|
||
| src/main.rs | CLI命令定义(scan/hash)|
|
||
| src/filetree/mod.rs | FileTree::init_user_db |
|
||
| data/users/warren.sqlite | warren用户数据库(12658 nodes)|
|
||
|
||
---
|
||
|
||
**最后更新:** 2026-05-17 02:15
|
||
**版本:** 1.7(File Scan System版)
|