Skip to main content

GlobalHub API (中央匯入與分發服務)

📋 基本資訊

📖 專案描述

GlobalHub API 是基於 .NET 10 建構的中央層後端服務,採用領域驅動設計 (Domain-Driven Design, DDD)整潔架構 (Clean Architecture) 原則開發。

架構定位

中央層 (Central)
├─ SERP API (外部供應商)
├─ GlobalHub API (本專案) ← 中央匯入與分發服務
└─ GlobalHub ← 中央 B2C 前台

區域層 (Regions: TW, US, JP)
├─ ProductsAPI ← 接收同步
├─ ProductBackend
└─ 區域 B2C 前台

核心職責 ⭐

A. 上游同步 (SERP → GlobalHub)

  • 從 SERP API 匯入產品資料(團體旅遊、票券)
  • 資料驗證與轉換
  • AI 資料豐富化(多語言翻譯、描述優化)
  • 儲存到中央資料庫

B. 下游同步 (GlobalHub → 各區域)

  • 推送產品到 ProductsAPI (TW/US/JP)
  • 區域化資料轉換
  • 批次同步與錯誤處理

C. 中央產品展示

  • 提供 GlobalHub 前台所需的產品 API

🏗️ 專案架構

目錄結構

globalhubapi/
├── src/
│ ├── Domain/ # 領域層 (業務邏輯核心)
│ │ ├── Product/ # 產品領域模型
│ │ │ ├── Product.cs
│ │ │ ├── ProductTranslation.cs
│ │ │ ├── ProductPrice.cs
│ │ │ ├── ImportJob.cs
│ │ │ └── RegionSyncLog.cs
│ │ ├── Domain.csproj
│ │ └── bin/, obj/
│ ├── Application/ # 應用層 (用例/業務流程)
│ │ ├── Abstractions/ # 介面定義
│ │ ├── Products/ # 產品相關用例
│ │ │ ├── Import/ # SERP 匯入邏輯
│ │ │ │ ├── ImportProductsCommand.cs
│ │ │ │ └── ImportProductsCommandHandler.cs
│ │ │ └── Sync/ # 區域同步邏輯
│ │ │ ├── SyncToRegionCommand.cs
│ │ │ └── SyncToRegionCommandHandler.cs
│ │ ├── Application.csproj
│ │ └── bin/, obj/
│ ├── Infrastructure/ # 基礎設施層 (外部依賴)
│ │ ├── Database/ # 資料庫設定
│ │ │ ├── ApplicationDbContext.cs
│ │ │ └── Configurations/
│ │ ├── Migrations/ # EF Core 遷移
│ │ ├── BackgroundJobs/ # Hangfire 背景任務
│ │ │ ├── ImportProductsJob.cs
│ │ │ └── RegionSyncJob.cs
│ │ ├── ExternalServices/ # 外部服務
│ │ │ ├── SerpApiClient.cs # SERP API 客戶端
│ │ │ └── RegionApiClient.cs # 區域 API 客戶端
│ │ ├── Infrastructure.csproj
│ │ └── bin/, obj/
│ ├── Presentation/
│ │ └── Web.Api/ # Web API 層
│ │ ├── Endpoints/
│ │ │ ├── Products/ # 產品端點
│ │ │ ├── Import/ # 匯入端點
│ │ │ ├── Sync/ # 同步端點
│ │ │ └── Webhooks/ # Webhook 端點
│ │ └── Program.cs
│ └── SharedKernel/ # 共享核心
│ ├── Entity.cs
│ ├── Error.cs
│ ├── ErrorType.cs
│ ├── IDomainEvent.cs
│ ├── Result.cs
│ ├── ValidationError.cs
│ └── SharedKernel.csproj
├── .vscode/ # VS Code 設定
├── .github/ # GitHub 專用資源
│ ├── instructions/ # 架構最佳實踐指南
│ ├── prompts/ # 開發 Prompts
│ └── agents/ # AI Agent 設定
├── GlobalHubApi.sln # Visual Studio 方案檔
├── Directory.Build.props # MSBuild 全域屬性
├── Directory.Packages.props # NuGet 套件版本管理
├── global.json # .NET SDK 版本
├── Dockerfile # Docker 容器化
├── .gitlab-ci.yml # GitLab CI/CD
└── README.md

技術棧詳細

後端框架

  • .NET 10 - 最新版 .NET (ASP.NET Core)
  • Entity Framework Core - ORM 框架
  • PostgreSQL - 關聯式資料庫(中央資料庫)

背景任務

  • Hangfire - 分散式背景任務處理

錯誤處理與重試

  • Polly - 重試策略與斷路器

監控

  • Prometheus - 指標收集
  • Serilog + Seq - 結構化日誌

架構模式

  • DDD (Domain-Driven Design) - 領域驅動設計
  • Clean Architecture - 整潔架構(依賴反轉)
  • CQRS - 命令查詢職責分離(部分實作)

容器化

  • Docker - 容器化部署

🔌 API 文件

主要端點

上游同步 (SERP 匯入)

方法端點說明回傳狀態
POST/api/products/import啟動 SERP 匯入任務202 Accepted, 400 BadRequest
GET/api/products/import/{jobId}查詢匯入任務狀態200 OK, 404 NotFound
POST/api/webhooks/serp接收 SERP Webhook 事件200 OK, 401 Unauthorized

下游同步 (分發到區域)

方法端點說明回傳狀態
POST/api/sync/regions同步到所有區域202 Accepted
POST/api/sync/regions/{code}同步到特定區域 (TW/US/JP)202 Accepted, 404 NotFound
GET/api/sync/regions/{code}/status查詢區域同步狀態200 OK

監控與健康檢查

方法端點說明回傳狀態
GET/health服務健康檢查200 OK, 503 Unavailable
GET/health/sync同步機制健康檢查200 OK, 503 Unavailable
GET/hangfireHangfire Dashboard-

API 設計原則

  • 非同步優先 - 長時間操作立即回傳 202 Accepted,提供 Job ID 追蹤
  • Result Pattern - 使用 Result<T> 處理錯誤,避免例外影響效能
  • 冪等性 - 重複呼叫不會造成重複處理
  • 領域事件 - 使用 Domain Events 處理副作用

💾 資料模型

Domain Layer

Product Domain

public class Product : Entity
{
public Guid Id { get; set; }
public string ExternalProductId { get; set; } // SERP Product ID
public string SupplierId { get; set; } // "SERP"

// 基本資訊
public string Name { get; set; }
public string Description { get; set; }
public ProductType ProductType { get; set; }

// 多語言內容
public List<ProductTranslation> Translations { get; set; }

// 多幣別價格
public List<ProductPrice> Prices { get; set; }

// AI 豐富化
public string? EnrichedDescription { get; set; }
public List<string>? Tags { get; set; }

// 時間戳記
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
}

public class ImportJob : Entity
{
public Guid Id { get; set; }
public string SupplierId { get; set; }
public ImportJobStatus Status { get; set; }
public ImportTrigger Trigger { get; set; }

public int TotalProcessed { get; set; }
public int SuccessCount { get; set; }
public int FailedCount { get; set; }

public DateTime CreatedAt { get; set; }
public DateTime? CompletedAt { get; set; }
}

public class RegionSyncLog : Entity
{
public Guid Id { get; set; }
public string RegionCode { get; set; } // TW, US, JP
public int ProductCount { get; set; }
public int SuccessCount { get; set; }
public int FailedCount { get; set; }
public SyncStatus Status { get; set; }

public DateTime StartedAt { get; set; }
public DateTime? CompletedAt { get; set; }
}

SharedKernel

核心共享元件:

// 基礎實體
public abstract class Entity
{
public Guid Id { get; protected set; }
}

// Result Pattern (錯誤處理)
public class Result<T>
{
public bool IsSuccess { get; }
public T Value { get; }
public Error Error { get; }
}

// 錯誤定義
public record Error(string Code, string Description, ErrorType Type);

// 領域事件介面
public interface IDomainEvent
{
Guid Id { get; }
DateTime OccurredOn { get; }
}

🔄 同步機制

上游同步:SERP → GlobalHub

觸發方式:

  1. Webhook (即時) - SERP 推送產品變更事件 ⭐ 優先
  2. 定時輪詢 - Hangfire Recurring Jobs
    • 全量同步: 每天凌晨 2:00 AM
    • 增量同步: 每小時
    • 價格同步: 每 15 分鐘
  3. 手動觸發 - 管理員手動執行

處理流程:

SERP API
↓ HTTP/JSON
SerpApiClient
↓ 驗證
SerpProductMapper
↓ 轉換
ProductEnrichmentService (AI)
↓ 豐富化
ImportProductsJob (Hangfire)
↓ 批次儲存
中央 PostgreSQL

下游同步:GlobalHub → 各區域

觸發方式:

  1. 定時排程 - Hangfire Recurring Jobs
    • TW: 每 30 分鐘
    • US: 每天凌晨 3:00 AM
    • JP: 每天凌晨 4:00 AM
  2. Webhook 觸發 - SERP 事件後自動推送
  3. 手動觸發 - 管理員手動同步

處理流程:

GlobalHub API (RegionSyncService)
↓ 批次處理 (50個/批)
├─ TW: POST /api/products/sync-from-globalhub
├─ US: POST /api/products/sync-from-globalhub
└─ JP: POST /api/products/sync-from-globalhub

ProductsAPI (各區域)
↓ 冪等性處理
├─ 儲存 PostgreSQL
└─ 同步 Elasticsearch

詳細設計: GlobalHub 同步架構

🔗 相關專案

上游整合

專案關係說明
SERP API外部供應商提供旅遊產品資料

中央層專案

專案關係說明
globalhub前端 (中央)消費 GlobalHub API 的中央前台

區域層專案

專案關係說明
productsapi下游服務 (區域)接收同步的產品資料
productbackend管理後台 (區域)區域產品內容管理

🚀 開發指南

環境需求

  • .NET 10 SDK
  • PostgreSQL (本地或 Docker)
  • IDE: Visual Studio 2022 / Rider / VS Code

本地執行

  1. 確保資料庫設定

    檢查 appsettings.json 中的 Database 連線字串:

    {
    "ConnectionStrings": {
    "Database": "Host=localhost;Port=5432;Database=globalhubdb;Username=postgres;Password=yourpassword"
    },
    "Regions": {
    "TW": {
    "ApiUrl": "https://tw.productsapi.liontravel.com",
    "ApiKey": "tw_api_key_here"
    }
    }
    }
  2. 執行專案

    dotnet run --project src/Presentation/Web.Api/Web.Api.csproj
  3. 執行 Migrations

    dotnet ef database update --project src/Infrastructure

Docker 執行

  1. 建構映像檔

    docker build -t globalhubapi .
  2. 啟動容器

    docker run -d -p 8080:8080 --name globalhubapi \
    -e ConnectionStrings__Database="Host=host.docker.internal;Port=5432;Database=globalhubdb;Username=postgres;Password=yourpassword" \
    globalhubapi

測試

dotnet test

🏛️ 架構層次

1. Domain Layer (領域層)

  • 無外部依賴 - 純業務邏輯
  • 實體與值物件 - Product, ImportJob, RegionSyncLog
  • 領域事件 - ProductImported, ProductSynced

2. Application Layer (應用層)

  • 用例實作 - 產品匯入、區域同步
  • CQRS Handlers - 命令與查詢處理器
  • 介面定義 - Repository、Service 介面

3. Infrastructure Layer (基礎設施層)

  • 資料庫實作 - EF Core DbContext
  • 外部服務 - SERP API Client, Region API Client
  • 背景任務 - Hangfire Jobs (Import, Sync)

4. Presentation Layer (展示層)

  • Web API - ASP.NET Core Minimal API
  • DTO - 資料傳輸物件
  • 驗證 - FluentValidation

🔄 背景任務 (Hangfire)

支援的任務

上游同步

  • SERP 全量同步 - 每天凌晨 2:00 AM
  • SERP 增量同步 - 每小時
  • SERP 價格同步 - 每 15 分鐘

下游同步

  • TW 區域同步 - 每 30 分鐘
  • US 區域同步 - 每天凌晨 3:00 AM
  • JP 區域同步 - 每天凌晨 4:00 AM

Hangfire Dashboard

存取 /hangfire 查看任務執行狀態、重試記錄、失敗日誌。

📊 監控與告警

Prometheus Metrics

  • globalhub_serp_sync_total{status} - SERP 同步總次數
  • globalhub_region_sync_total{region,status} - 區域同步總次數
  • globalhub_sync_duration_seconds{sync_type} - 同步耗時
  • globalhub_last_sync_timestamp{source} - 最後同步時間

健康檢查

  • GET /health - 服務整體健康
  • GET /health/sync - 同步機制健康(檢查 SERP 與各區域)

告警規則

  • SERP 同步失敗率 > 10%
  • SERP 同步超過 1 小時未執行
  • 區域同步失敗
  • 同步時間 P95 > 5 分鐘

📝 CI/CD 流程

.gitlab-ci.yml 支援以下階段:

  1. Build - 編譯專案
  2. Test - 執行單元測試與整合測試
  3. Publish - 建置 Docker 映像檔並推送到 Registry
  4. Deploy - 部署到目標環境

🎯 設計決策

為何選擇 Clean Architecture?

  1. 可測試性 - 業務邏輯獨立於框架
  2. 可維護性 - 清晰的層次分離
  3. 可擴展性 - 易於替換基礎設施組件

為何使用 Hangfire?

  1. 可靠性 - 任務持久化,伺服器重啟不丟失
  2. 監控 - 內建 Dashboard
  3. 易用性 - .NET 原生整合

為何採用 Result Pattern?

  1. 效能 - 避免例外拋出的效能成本
  2. 明確性 - 強制處理錯誤情況
  3. 型別安全 - 編譯期檢查

為何雙向同步架構?

  1. 中央採購 - 統一從 SERP 取得產品
  2. 區域運營 - 各區域獨立管理與銷售
  3. 資料主權 - 區域資料留在區域資料庫

🔐 安全性

  • 輸入驗證 - FluentValidation
  • SQL Injection 防護 - EF Core 參數化查詢
  • API Key 驗證 - Webhook 簽章驗證
  • 敏感資料 - 使用 User Secrets / 環境變數

📚 相關文件