---
document_type: "architecture_design"
service: "MOMENTRY_CORE"
title: "Momentry Core 全域服務資源管理架構 (v1.0)"
date: "2026-04-21"
version: "V1.0"
status: "active"
owner: "Warren"
created_by: "OpenCode"
tags:
  - "momentry"
  - "core"
  - "全域服務資源管理架構"
ai_query_hints:
  - "查詢 Momentry Core 全域服務資源管理架構 (v1.0) 的內容"
  - "Momentry Core 全域服務資源管理架構 (v1.0) 的主要目的是什麼？"
  - "如何操作或實施 Momentry Core 全域服務資源管理架構 (v1.0)？"
---

# Momentry Core 全域服務資源管理架構 (v1.0)

| 項目 | 內容 |
|------|------|
| 建立者 | OpenCode |
| 建立時間 | 2026-04-21 |
| 文件版本 | V1.0 |

---

## 版本歷史

| 版本 | 日期 | 目的 | 操作人 | 工具/模型 |
|------|------|------|--------|-----------|
| V1.0 | 2026-04-21 | 創建全域服務資源管理架構文件 | OpenCode | OpenCode / Qwen3.6-Plus |

---

## 0. 設計目標

將所有基礎設施服務（Infrastructure Services）視為**可管理資源**，實現：

1. **動態發現**: 處理器不再寫死服務 IP，而是從註冊中心查詢可用服務
2. **健康監控**: 自動探活服務狀態，故障時標記並尋找備用節點
3. **版本追溯**: 精確記錄模型檔案、配置、依賴關係，確保可重現性
4. **運維自動化**: 統一管理備份、日誌、儲存路徑，降低人工維護成本

---

## 1. 核心架構

### 1.1 服務分類 (Service Types)

| 類型 | 說明 | 範例 |
|------|------|------|
| `embedding_engine` | 語意向量生成 | Ollama (nomic-embed-text-v2-moe) |
| `llm_engine` | 文字生成/推理 | llama.cpp (gemma-4) |
| `vector_db` | 向量儲存與搜尋 | Qdrant |
| `cache` | 快取與隊列 | Redis |
| `database` | 關聯式資料庫 | PostgreSQL |
| `storage` | 檔案管理 | SFTPGo |
| `api_server` | API 閘道 | Momentry Core Server |

### 1.2 服務資源關聯圖

```
使用者/API
    │
    ├──> [Momentry Core API Server] (api_server)
    │       │
    │       ├──> [Qdrant] (vector_db) ─── 向量搜尋
    │       │
    │       ├──> [Ollama] (embedding_engine) ─── 768-dim Embedding
    │       │
    │       ├──> [llama.cpp] (llm_engine) ─── Gemma4 推理
    │       │
    │       ├──> [PostgreSQL] (database) ─── 關聯資料
    │       │
    │       └──> [Redis] (cache) ─── 快取與隊列
    │
    └──> [SFTPGo] (storage) ─── 檔案上傳/管理
```

---

## 2. 資料庫設計

### 2.1 `services` 表結構

```sql
CREATE TABLE services (
    id UUID PRIMARY KEY,
    name VARCHAR(100) NOT NULL,              -- 服務名稱 (e.g., ollama-embedding-nomic-v2-moe)
    type VARCHAR(50) NOT NULL,               -- 服務類型 (見 1.1)
    endpoint VARCHAR(255),                   -- 基礎連接點 (e.g., http://127.0.0.1:11434)
    status VARCHAR(20) DEFAULT 'unknown',    -- online, offline, degraded, unknown
    metadata JSONB,                          -- 技術細節 (模型版本、維度等)

    -- 1. 網路與端口
    port_config JSONB,                       -- 主端口、範圍、協議

    -- 2. 存取控制
    access_policy JSONB,                     -- 認證方式、允許的使用者

    -- 3. 依賴關係
    dependency_graph JSONB,                  -- 上游/下游依賴

    -- 4. 業務上下文
    business_purpose TEXT,                   -- 用途說明
    reference_docs JSONB,                    -- 文檔連結

    -- 5. 儲存與日誌
    storage_paths JSONB,                     -- 配置、數據、log、error_log

    -- 6. 備份策略
    backup_policy JSONB,                     -- 備份週期、方法、目標

    -- 7. 健康檢查
    health_check_path VARCHAR(255),          -- 探活路徑 (e.g., /health)
    health_check_method VARCHAR(10),         -- HTTP 方法 (GET/POST)
    health_check_match TEXT,                 -- 預期回應 (Status 200 or JSON content)
    check_interval_secs INT DEFAULT 60,      -- 檢查頻率 (秒)

    last_check_at TIMESTAMPTZ,
    created_at TIMESTAMPTZ DEFAULT NOW()
);
```

---

## 3. 欄位詳細說明

### 3.1 技術細節 (metadata)

根據服務類型記錄不同的技術參數。

**Ollama (Embedding Engine)**:
```json
{
    "provider": "ollama",
    "model_name": "nomic-embed-text-v2-moe",
    "model_tag": "latest",
    "gguf_file": "nomic-embed-text-v2-moe-Q4_0.gguf",
    "gguf_sha256": "sha256:xxxxx...",
    "source_url": "https://huggingface.co/nomic-ai/nomic-embed-text-v2-moe-GGUF",
    "dimensions": 768,
    "capabilities": ["embedding", "text-similarity", "multilingual"],
    "context_length": 2048,
    "architecture": "Mixture of Experts (MoE)"
}
```

**llama.cpp (LLM Engine)**:
```json
{
    "provider": "llama.cpp",
    "model_name": "gemma-4-12b-it",
    "model_file": "gemma-4-12b-it-Q4_K_M.gguf",
    "source": "https://huggingface.co/bartowski/gemma-4-12b-it-GGUF",
    "sha256": "sha256:yyyyy...",
    "capabilities": ["text-generation", "chat"],
    "parameters": "12B",
    "quantization": "Q4_K_M",
    "gpu_layers": -1
}
```

### 3.2 網路與端口 (port_config)

```json
{
    "main_port": 11434,
    "range": "11434-11435",
    "protocol": "HTTP",
    "bind_address": "127.0.0.1"
}
```

### 3.3 存取控制 (access_policy)

```json
{
    "auth_type": "none",
    "allowed_users": ["momentry_core", "vectorize_worker"],
    "api_key_env": null,
    "rate_limit": "unlimited",
    "cors_origin": "localhost"
}
```

### 3.4 依賴關係 (dependency_graph)

```json
{
    "upstream": ["gpu_driver", "cuda_toolkit"],
    "downstream": ["qdrant_ingestion", "search_api", "smart_synonym_expander"],
    "criticality": "high"
}
```

### 3.5 儲存與日誌 (storage_paths)

```json
{
    "data_dir": "/Users/accusys/.ollama/models",
    "config_dir": "/Users/accusys/.ollama/modelfiles",
    "log_file": "/Users/accusys/Library/Logs/ollama/ollama.log",
    "error_log_file": "/Users/accusys/Library/Logs/ollama/ollama.error.log",
    "env_file": "/Users/accusys/.ollama/.env"
}
```

### 3.6 備份策略 (backup_policy)

```json
{
    "enabled": true,
    "method": "rsync",
    "schedule": "daily",
    "destination": "/Volumes/BackupDrive/momentry_services/ollama",
    "retention_days": 30,
    "pre_hook": "launchctl stop com.ollama.service",
    "post_hook": "launchctl start com.ollama.service",
    "exclude_patterns": ["*.tmp", "logs/*"]
}
```

### 3.7 健康檢查 (health_check)

| 欄位 | 說明 | 範例 |
|------|------|------|
| `health_check_path` | 探活路徑 | `/health` 或 `/` |
| `health_check_method` | HTTP 方法 | `GET` |
| `health_check_match` | 預期回應內容 | `Ollama is running` |
| `check_interval_secs` | 檢查頻率 | `60` |

---

## 4. 完整註冊範例

### 4.1 Ollama Embedding Engine

```sql
INSERT INTO services (
    id, name, type, endpoint, status, metadata,
    port_config, access_policy, dependency_graph,
    business_purpose, reference_docs,
    storage_paths, backup_policy,
    health_check_path, health_check_method, health_check_match, check_interval_secs
) VALUES (
    '550e8400-e29b-41d4-a716-446655440100',
    'ollama-embedding-nomic-v2-moe',
    'embedding_engine',
    'http://127.0.0.1:11434',
    'online',
    '{"provider": "ollama", "model_name": "nomic-embed-text-v2-moe", "model_tag": "latest", "dimensions": 768}'::jsonb,
    '{"main_port": 11434, "protocol": "HTTP"}'::jsonb,
    '{"auth_type": "none", "allowed_users": ["momentry_core", "vectorize_worker"]}'::jsonb,
    '{"upstream": ["gpu_driver"], "downstream": ["qdrant_ingestion", "search_api"], "criticality": "high"}'::jsonb,
    'Generate 768-dim multilingual embeddings for chunks and semantic search.',
    '{"model_url": "https://ollama.com/library/nomic-embed-text-v2-moe", "wiki": "docs/PROCESSING_PIPELINE.md"}'::jsonb,
    '{
        "data_dir": "/Users/accusys/.ollama/models",
        "config_dir": "/Users/accusys/.ollama/modelfiles",
        "log_file": "/Users/accusys/Library/Logs/ollama/ollama.log",
        "error_log_file": "/Users/accusys/Library/Logs/ollama/ollama.error.log"
    }'::jsonb,
    '{
        "enabled": true,
        "method": "rsync",
        "destination": "/Volumes/BackupDrive/ollama_models",
        "retention_days": 30
    }'::jsonb,
    '/', 'GET', 'Ollama is running', 60
);
```

### 4.2 llama.cpp LLM Engine

```sql
INSERT INTO services (
    id, name, type, endpoint, status, metadata,
    port_config, access_policy, dependency_graph,
    business_purpose, reference_docs,
    storage_paths, backup_policy,
    health_check_path, health_check_method, health_check_match, check_interval_secs
) VALUES (
    '550e8400-e29b-41d4-a716-446655440099',
    'llama-server-gemma4',
    'llm_engine',
    'http://127.0.0.1:8081',
    'online',
    '{"provider": "llama.cpp", "model_name": "gemma-4-12b-it", "model_file": "gemma-4-12b-it-Q4_K_M.gguf", "capabilities": ["text-generation", "chat"], "parameters": "12B"}'::jsonb,
    '{"main_port": 8081, "protocol": "HTTP"}'::jsonb,
    '{"auth_type": "none", "allowed_users": ["momentry_core"]}'::jsonb,
    '{"upstream": ["gpu_driver"], "downstream": ["smart_synonym_expander", "query_parser"], "criticality": "medium"}'::jsonb,
    'Provide text generation and instruction following for synonym expansion and query analysis.',
    '{"model_url": "https://huggingface.co/bartowski/gemma-4-12b-it-GGUF"}'::jsonb,
    '{
        "data_dir": "/Users/accusys/momentry/models",
        "config_dir": "/Users/accusys/momentry/config",
        "log_file": "/Users/accusys/momentry/logs/llama_server.log",
        "error_log_file": "/Users/accusys/momentry/logs/llama_server.error.log"
    }'::jsonb,
    '{
        "enabled": true,
        "method": "rsync",
        "destination": "/Volumes/BackupDrive/llama_models",
        "retention_days": 30
    }'::jsonb,
    '/health', 'GET', 'OK', 30
);
```

### 4.3 Qdrant Vector DB

```sql
INSERT INTO services (
    id, name, type, endpoint, status, metadata,
    port_config, access_policy, dependency_graph,
    business_purpose, reference_docs,
    storage_paths, backup_policy,
    health_check_path, health_check_method, health_check_match, check_interval_secs
) VALUES (
    '550e8400-e29b-41d4-a716-446655440003',
    'qdrant-vector-store',
    'vector_db',
    'http://127.0.0.1:6333',
    'online',
    '{"version": "1.7.0", "collections": ["momentry_rule1", "momentry_rule2", "momentry_rule3"], "vector_dim": 768, "distance": "Cosine"}'::jsonb,
    '{"main_port": 6333, "grpc_port": 6334, "protocol": "HTTP/REST+gRPC"}'::jsonb,
    '{"auth_type": "api_key", "api_key_env": "QDRANT_API_KEY", "allowed_users": ["momentry_core", "vectorize_worker"]}'::jsonb,
    '{"upstream": ["ollama-embedding-nomic-v2-moe"], "downstream": ["search_api"], "criticality": "critical"}'::jsonb,
    'Store and search 768-dim embeddings for all chunk rules.',
    '{"docs": "https://qdrant.tech/documentation"}'::jsonb,
    '{
        "data_dir": "/opt/qdrant/storage",
        "config_dir": "/opt/qdrant/config",
        "log_file": "/var/log/qdrant/qdrant.log",
        "error_log_file": "/var/log/qdrant/qdrant.error.log"
    }'::jsonb,
    '{
        "enabled": true,
        "method": "snapshot",
        "schedule": "daily",
        "destination": "/Volumes/BackupDrive/qdrant_snapshots",
        "retention_days": 14
    }'::jsonb,
    '/healthz', 'GET', '', 30
);
```

---

## 5. 健康監控機制 (Health Monitor)

### 5.1 監控流程

```
1. Worker 掃描 services 表 (status != 'disabled')
   ↓
2. 對每個服務發送 health_check
   - URL: endpoint + health_check_path
   - Method: health_check_method
   ↓
3. 驗證回應
   - HTTP Status: 200 OK?
   - Content: 包含 health_check_match?
   ↓
4. 更新狀態
   - success → status = 'online'
   - fail → status = 'offline'
   - timeout → status = 'degraded'
   ↓
5. 記錄 last_check_at
```

### 5.2 Rust 實作範例

```rust
pub async fn run_health_checks(pool: &PgPool) -> anyhow::Result<()> {
    let services = sqlx::query!(
        "SELECT id, endpoint, health_check_path, health_check_method, 
                health_check_match, check_interval_secs 
         FROM services WHERE status != 'disabled'"
    )
    .fetch_all(pool)
    .await?;

    for svc in services {
        let url = format!("{}{}", svc.endpoint, svc.health_check_path);
        let new_status = match check_service_health(&url, &svc.health_check_method).await {
            Ok(body) => {
                if let Some(expected) = &svc.health_check_match {
                    if body.contains(expected) { "online" } else { "degraded" }
                } else { "online" }
            }
            Err(_) => "offline"
        };

        sqlx::query!(
            "UPDATE services SET status = $1, last_check_at = NOW() WHERE id = $2",
            new_status,
            svc.id
        )
        .execute(pool)
        .await?;
    }
    Ok(())
}
```

---

## 6. 依賴影響分析

### 6.1 故障傳播查詢

```sql
-- 查詢受 Ollama 故障影響的所有服務
SELECT name, type, status
FROM services
WHERE dependency_graph->'upstream' @> '["ollama-embedding-nomic-v2-moe"]';

-- 查詢 Qdrant 依賴的所有上游服務
SELECT name, type, status
FROM services
WHERE 'qdrant-vector-store' = ANY(
    ARRAY(
        SELECT jsonb_array_elements_text(
            dependency_graph->'downstream'
        )
    )
);
```

### 6.2 啟動順序

根據 `dependency_graph` 的 `upstream` 字段，系統可自動計算服務啟動順序：

```
1. gpu_driver → cuda_toolkit
2. ollama-embedding-nomic-v2-moe (需要 gpu_driver)
3. llama-server-gemma4 (需要 gpu_driver)
4. qdrant-vector-store
5. redis-cache
6. postgres-main
7. momentry-core-api (依賴以上所有)
```

---

## 7. 備份管理 (Backup Manager)

### 7.1 備份排程查詢

```sql
-- 找出今日需要備份的服務
SELECT name, backup_policy
FROM services
WHERE backup_policy->>'enabled' = 'true'
  AND (backup_policy->>'schedule' = 'daily' 
       OR backup_policy->>'schedule' LIKE '%* * *');
```

### 7.2 備份執行邏輯

```
1. Worker 掃描 backup_policy.enabled = true
   ↓
2. 執行 pre_hook (如停止服務)
   ↓
3. 執行備份方法
   - rsync: rsync -a --exclude="*.tmp" data_dir destination
   - pg_dump: pg_dump dbname > destination/dump.sql
   - snapshot: qdrant CLI create-snapshot
   ↓
4. 壓縮 (gzip)
   ↓
5. 執行 post_hook (如重啟服務)
   ↓
6. 清理超過 retention_days 的舊備份
```

---

## 8. 總結

本設計將所有基礎設施服務納管為**可發現、可監控、可備份、可追溯**的資源實體。

| 管理維度 | 實作方式 |
|----------|----------|
| **服務發現** | `services` 表 + `endpoint` 欄位 |
| **版本追溯** | `metadata` (模型檔案 SHA256, 版本號) |
| **健康監控** | `health_check_*` 欄位 + 背景 Worker |
| **依賴管理** | `dependency_graph` (upstream/downstream) |
| **存取控制** | `access_policy` (認證方式、允許使用者) |
| **儲存管理** | `storage_paths` (配置、數據、分離日誌) |
| **備份恢復** | `backup_policy` (排程、方法、保留期、Hooks) |

透過此架構，Momentry 可實現從「手動運維」到「自動化服務治理」的升級。
