Files
awoooi/docs/adr/ADR-024-api-layer-architecture.md
OG T 6fed8be8c4
Some checks failed
E2E Health Check / e2e-health (push) Successful in 17s
Type Sync Check / check-type-sync (push) Failing after 22s
docs(adr): ADR-024 R4 Router 瘦身標記完成
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 09:27:40 +08:00

6.2 KiB
Raw Permalink Blame History

ADR-024: API 分層架構 (Phase 16 絞殺者模式)

項目 內容
狀態 已採用 (Phase R-R2 完成2026-04-01)
日期 2026-03-26
決策者 首席架構師 + 統帥
Phase Phase 16

背景

Phase 16 架構大掃除需要明確的 API 分層規範,以支援絞殺者模式 (Strangler Fig Pattern) 的漸進式重構。

當前問題:

  • Router 層存在業務邏輯 (32 項違規)
  • 配置分散在多處
  • 缺乏明確的層級邊界

決策

採用 四層架構 標準:

┌─────────────────────────────────────────────────┐
│  Router Layer (api/v1/*.py)                     │
│  - HTTP 轉發 ONLY                               │
│  - 參數驗證 (Pydantic)                          │
│  - 權限檢查 (Depends)                           │
│  - ❌ 禁止: Redis/DB/外部 API 直接呼叫         │
└─────────────────────────────────────────────────┘
                      │
                      ▼
┌─────────────────────────────────────────────────┐
│  Service Layer (services/*.py)                  │
│  - 業務邏輯                                     │
│  - 外部 API 封裝                                │
│  - 快取策略                                     │
│  - ✅ 可呼叫: Repository, 其他 Service          │
└─────────────────────────────────────────────────┘
                      │
                      ▼
┌─────────────────────────────────────────────────┐
│  Repository Layer (repositories/*.py)           │
│  - 資料存取抽象                                 │
│  - SQL/ORM 操作                                 │
│  - Redis 快取                                   │
│  - ✅ 可呼叫: Model, Redis, PostgreSQL          │
└─────────────────────────────────────────────────┘
                      │
                      ▼
┌─────────────────────────────────────────────────┐
│  Model Layer (models/*.py)                      │
│  - Pydantic Schema                              │
│  - SQLAlchemy ORM                               │
│  - 純資料結構,無邏輯                           │
└─────────────────────────────────────────────────┘

Router 層禁止清單

# ❌ 禁止在 Router 層做的事

# 1. 直接 Redis 存取
from src.core.redis_client import get_redis  # ❌

# 2. 直接 DB Session
from src.db.base import get_session  # ❌

# 3. 直接外部 API 呼叫
async with httpx.AsyncClient() as client:  # ❌
    response = await client.get(external_url)

# 4. 內嵌 Lua 腳本
LUA_SCRIPT = """..."""  # ❌

# 5. 複雜業務邏輯 (>10 行)
if condition1 and condition2:  # ❌
    # 複雜處理...

Router 層允許清單

# ✅ Router 層可以做的事

# 1. 參數驗證
@router.get("/items/{item_id}")
async def get_item(
    item_id: str = Path(...),
    limit: int = Query(default=10, ge=1, le=100),
) -> ItemResponse:

# 2. 權限檢查
async def get_item(
    current_user: User = Depends(get_current_user),
):

# 3. 呼叫 Service
service = get_item_service()
result = await service.get_item(item_id)

# 4. 回傳轉換 (簡單)
return ItemResponse.from_orm(result)

絞殺者模式四階段

Phase 1: Identify (識別)
├── 標記現有違規代碼
├── 建立 Service 介面
└── 不改變行為

Phase 2: Deprecate (標記棄用)
├── 新代碼使用 Service
├── 舊代碼加 @deprecated
└── 監控舊路徑使用量

Phase 3: Migrate (遷移)
├── 逐步遷移到 Service
├── 每次遷移有測試覆蓋
└── 回滾計畫就緒

Phase 4: Remove (移除)
├── 確認無流量
├── 移除舊代碼
└── 更新文檔

與 leWOOOgo 積木化的關係

leWOOOgo 六大積木        API 四層對應
─────────────────────────────────────
BRAIN (決策)      →    Service Layer
ACTION (執行)     →    Service + Repository
SENSE (感知)      →    Repository Layer
MEMORY (記憶)     →    Repository Layer
OUTPUT (輸出)     →    Service Layer
SAFETY (安全)     →    Router (Depends) + Service

回滾策略

# 功能開關 (core/config.py)
USE_NEW_LAYER: bool = Field(
    default=False,
    description="True=新分層, False=舊版內嵌",
)

# 回滾指令
kubectl set env deployment/awoooi-api USE_NEW_LAYER=false

後果

正面

  • 清晰的層級邊界
  • 可測試性提升 (每層獨立測試)
  • 漸進式遷移,低風險

負面

  • 短期開發成本增加
  • 需要團隊學習新規範

執行進度

Phase 任務 狀態 Commit
R1 絞殺者包裝 (USE_NEW_ENGINE) Phase 16 R1
R2 移除內嵌重複邏輯 c7b3f8f (2026-04-01)
R3 抽取 Repository 層 Phase 22 (repositories/)
R4 瘦身 Router 層 4118808 (2026-04-01)

Phase R-R2.1 首席架構師正式審查72/100 條件通過。 P0+P1 全部修復。P2 技術債清單見 ADR-046。 回滾方式已更新git revert c7b3f8f d17b67c + kubectl rollout restart (USE_NEW_ENGINE 旗標已失效)。

相關文件

  • ADR-005: BFF Architecture
  • ADR-003: leWOOOgo Module Architecture
  • ADR-046: 跨套件 Incident 型別統一 (BrainIncident vs local Incident)
  • feedback_strangler_fig_pattern.md
  • reference_phase16_architecture.md