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

188 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 層禁止清單
```python
# ❌ 禁止在 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 層允許清單
```python
# ✅ 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
```
## 回滾策略
```yaml
# 功能開關 (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`