iT邦幫忙

2025 iThome 鐵人賽

DAY 13
0
Software Development

Codetopia 新手日記:設計模式與原則的 30 天學習之旅系列 第 30

Day 30:多代理終章:「潮汐書市」與夜跑動線的世紀大和解!

  • 分享至 

  • xImage
  •  

Codetopia 創城記 (30)|多代理終章:「潮汐書市」與夜跑動線的世紀大和解!

1) 今日熱點 (故事開場 & 痛點) ⚡️

故事要從一個濕熱的週六傍晚說起。地點?河灣新落成的「潮汐書市」,旁邊就是市民最愛的環河夜跑步道。時間?晚間六點四十分,天空不巧地飄起了毛毛細雨。原本,這該是兩個互不相干的美好日常,書香與汗水各自安好。

但命運,總喜歡在週六晚上開個大玩笑。

混亂的種子,其實早在幾週前就埋下了。路跑聯盟的活動,是循規蹈矩地在交通局的系統裡登記、審批、排程的「乖寶寶」。而書市的「作者簽名會延長」,則是在活動當天,由一位興高采烈、腎上腺素飆升的社群小編,在臉書粉絲頁上勇敢地按下了「發佈」按鈕。

(是的,一個是寫在石頭上的律法,另一個是寫在沙灘上的情書。在 Codetopia 的數位世界裡,這兩者跟陌生人沒兩樣。)

於是,災難的雞尾酒就這樣調成了。主料是三個互不通話的訊息管道:臉書小編的熱情、交通局電子看板的冷漠、路跑 App 的準時。配料是那場恰到好處的雨。輕輕一搖,倒出來的就是現場那杯名為「人間煉獄」的特調。想帶著戰利品和作者簽名回家的書迷,迎面撞上了正在原地高抬腿熱身的跑者;推著嬰兒車想躲雨的家長,絕望地發現自己卡在了一群穿著螢光緊身衣的移動路障中間。

值班室的電話線燙得能煎蛋,志工的對講機裡,尖叫聲和求救聲糊成一鍋數位濃粥。終於,指揮中心的值班官員,抓著麥克風,發出了那句所有工程師都耳熟能詳的絕望嘶吼:「聽著!我需要你們在二十分鐘內變出一個奇蹟!還有,誰都不准給我動市民 App 的程式碼!

就在這片數位與現實交織的混亂中,一個冷靜的聲音切入頻道,像冰塊掉進了滾水:「收到。多代理臨時反應小隊,入場。」

Aster,多代理協作總監,來上班了。

2) 術語卡 🧭

  • MAS (Multi-Agent Systems):多個自主「代理人」透過協作解決單一代理無法處理的複雜問題,包含 DF (黃頁服務) 與 ACL (代理通訊語言)。

  • Contract-Net:一種任務分配協議,由一方「招標」,多方「投標」,實現去中心化的決策,避免「一神獨裁」。

  • Critic/Planner/Executor 迴圈:一種決策流程,由規劃者提出方案、批判者審查風險、執行者負責落實,確保每一步都可回放、可審計。

  • City Event Bus:城市事件總線,所有代理人溝通的唯一訊息入口,確保訊息傳遞的可靠性與一致性。(旁批:這條總線只傳遞「事實 (Events)」,不應把大型查詢結果塞進來!設計鐵律:查詢走同步 API 或快取、指令可走同步 API 或 command topic,事件只承載已發生的事實。)

3) 笑中帶淚 (反例/壞味道) 😭

在 Aster 小隊抵達前,有人曾試圖用「老方法」解決問題。讓我們把時間稍微往前調一點,看看那場華麗的失敗是如何上演的:

  1. 一個提示詞餵給神:有人寫了一段三百行的「超級提示詞」給一個全能的 AI 代理,內容包山包海,從疏散路線、天氣預測到安抚民眾情緒的廣播稿。「去吧!解決一切!」... 結果,那個代理產生了幻覺命令,建議大家「原地跳躍以保持溫暖」,還試圖同時呼叫所有交通號誌 API,直接踩爆了系統頻寬。

  2. 直接呼叫供應商 SDK:某個代理直接串接了電子看板供應商的 SDK,但該 SDK 回傳的亮度值是 01 的浮點數;而另一個廣播系統的音量單位卻是 0100 的整數。結果?看板亮到像白天,廣播卻小聲到像蚊子叫,行為完全無法對齊

  3. 無情的重試雪崩:一個指令因為網路抖動而超時,系統很自然地進行了重試。但因為沒有設計冪等性 (idempotency_key),同一個「封閉步道」的指令被執行了三次。於是,三組不同的柵欄被送到現場,造成了更大的混亂。

  4. 消失的決策軌跡:事後複盤時,沒人知道是「誰」在「哪個時間點」根據「哪一版規定」下達了「原地跳躍」的指令。記憶無法稽核,讓每一次災難都成了懸案。

4) 王牌出手 (核心觀念/何時用/不適用) 👑

Aster|多代理協作總監抵達後,沒有一絲慌亂。她打開了終端機,召集了她的菁英小隊,一場多代理協作就此展開。

  • Aster (總監) - 發包!不是發瘋:她立刻使用 Contract-Net (合約網協議) 發出兩個清晰的標案:

    • 標案 A / 動線調度:需求是「不更新市民 App,20 分鐘內解除人潮逆流」,SLA 要求極高。

    • 標案 B / 訊息一致性:需求是「一鍵同步真相 (SSOT) 到現場看板、手持廣播與官方社群」,確保資訊零時差。(旁批:這裡的一致性,是透過共享的語彙庫與模板中心來達成的,確保『延後十分鐘』在三個管道的說法完全一樣,杜絕人工轉述的語意誤差。)

  • Kian (工具鍛造師) - 穩定的插座,不是混亂的電線:他並未讓代理們直接去碰觸那些脾氣古怪的硬體 SDK。而是開啟了「城市工具庫」三個穩定的 Port (埠):RoutePortSignagePortBroadcastPort。所有工具的呼叫,都必須透過這些穩定 Port 進行;對外副作用以同步 API 或 command.* topic 發出,事件只承載已發生的事實,查詢走同步 API 或快取層(由 Adapter 觸碰 Bus,Domain 不直連)。

https://ithelp.ithome.com.tw/upload/images/20251014/20178500gCU8c9zgC2.png

_圖說小字:事件 publish/consume 僅在 Adapter/邊界層,Domain 不依賴 Bus 實作。_

他還再三強調:「事件 Schema 的演進,必須遵守只增不改的原則。新增欄位需為可選或具備預設值,任何破壞性變更的 PR 都會被 CI 自動退件,這是為了保障舊的代理不會因為新事件而崩潰!」
  • Rook (協商仲裁員) - 在安全與體驗間,跳一曲探戈:很快,動線規劃代理和使用者體驗代理吵起來了。「安全第一!應立刻全面封鎖步道!」「不行!書迷還沒走完,會引發恐慌!」Rook|協商仲裁員介入了。他調出 城市幸福指標 (CUPID) 的權重檔,一鍵導出折衷決策:立即開闢一條「安靜帶走線」供離場民眾使用,夜跑活動延後十分鐘,並採分批通行。雙方代理都接受了這個方案。

  • Sable (安全評審官) - 命令出口的最後一道防火牆:所有即將對外發出的命令,都必須經過 Sable 的審查。她為每個指令都套上了硬停 (hard stop)降級計畫 (rollback plan)

    • 若監測到現場人流密度超過 P95 警戒線,自動觸發備援方案:志工立刻舉起離線的 QR Code 手牌引導。

    • 她攔下了一個即將發出的廣播指令,冷靜地說:「『廣播』是不可逆的外部動作,沒有『回滾』這回事。」她要求改為兩階段提交 (Two-phase Publish):先發布一則 broadcast.previewed 內部審計事件,待所有相關方確認無誤後,才發出那則 broadcast.committed 事件。如果真的發錯了,只能發布 broadcast.corrected 來進行覆寫修正。(旁批:這稱為 Forward-Fix,是在不可逆操作上進行補救,而不是真正的『回滾』。)

    • 她還順手駁回了一個計畫,理由是:「冪等鍵和關聯 ID 裡,絕對不准包含任何市民個資 (PII)!這是紅線!」

https://ithelp.ithome.com.tw/upload/images/20251014/20178500zZIbodQSlj.png

_圖說小字:corrected 是 forward-fix,不是 rollback(呼應文中的紅線)。_
  • Ember (記憶管家) - 為每一次行動,都刻下時間戳記:她為這次任務創建了一個唯一的 ID:run_id=BOOKRUN-2210。所有決策、所有被採納的規則版本 (ordinance_version=v2025-10-12.1),都被精確地記錄下來,形成了一條可回放、可稽核的時光快照。想知道「回到剛剛」發生了什麼?問 Ember 就對了。

何時用 (When to Use)

  • 問題複雜且高度動態:當單一演算法或單一「神腦」無法應對環境的快速變化時,如智慧交通、供應鏈調度。

  • 需要去中心化決策:當任務可以被分解成多個子任務,且子任務間需要協商與合作時,如災難響應、資源分配。

  • 系統需具備韌性與可擴展性:單一代理的失敗不應導致整個系統崩潰,新增代理應能無縫融入協作網絡。

何時不要用 (When NOT to Use)

  • 問題簡單且流程固定:如果只是一個固定的 ETL 流程或簡單的 CRUD 操作,引入多代理無疑是殺雞用牛刀,會帶來不必要的複雜性。

  • 缺乏清晰的協作協議:如果無法定義代理之間清晰的溝通語言 (ACL) 和互動規則 (Protocol),它們會變成一盤散沙,甚至互相干擾。

  • 對即時性要求達到奈秒級:代理間的協商和通訊需要時間,對於高頻交易這類場景,多代理的通訊開銷可能無法接受。

  • 治理風險:當表面上是多代理,但所有決策實質上仍由單一代理或中心節點做出時,就形成了「中心化獨裁者 (Centralized Dictator)」的反模式,失去了去中心化的優勢。

5) 導播切景 (表格+兩張 Mermaid) 🎥

導播,鏡頭拉一下!讓我們看看這場精彩救援在不同尺度下的樣貌。

視角 觀念/模式 在本篇的說法
微觀 (GoF) Strategy / Observer / State 動線策略的即時切換;市民對廣播事件的觀察;電子看板與號誌的狀態流轉。
中觀 (EIP/EDA) Topic/Queue / Outbox+Inbox / Saga command.*events.*partition_key = run_id 投遞,保證局部有序;重試採 backoff+jitter,達上限則移入 DLQ 告警。
宏觀 (MAS) DF / ACL / Contract-Net Aster (總監) 透過 DF (黃頁) 招標,各代理以 ACL (通訊語言) 投標,Rook (仲裁員) 進行仲裁,Sable (守門員) 進行風險審查

https://ithelp.ithome.com.tw/upload/images/20251014/20178500kQZnalH5Nw.png

圖說小字:同一場域以 partition_key=run_id/venueId 投遞,保障局部有序;DLQ 觸發告警與人工介入流程。

事件包裝(最小欄位)

id topic type ts key(idempotency) correlationId causationId payload

硬規:Schema 只增不改;新增欄位需可選或具預設值;破壞性變更 CI 自動退件。

(旁批:事件的發布與消費,嚴格限制在六角架構的 Adapter/邊界層,核心領域 (Domain) 不應依賴任何 Bus 的實作細節。)

Mermaid|多代理收斂決策(簡化序列)

https://ithelp.ithome.com.tw/upload/images/20251014/20178500BPd0Jwwc4W.png

Mermaid|代理團隊結構(簡化類圖)

https://ithelp.ithome.com.tw/upload/images/20251014/20178500AnB1YOj6jX.png

6) 最小實作 (程式碼範例) 💻

讓我們看看 Aster 小隊的行動,如果翻譯成更嚴謹的 Python pseudo code,會是什麼樣子。

# --- 訊息結構 (Kian & Ember 的傑作) ---
# 注意:指令(Command)是意圖,事件(Event)是事實
# 兩者都包含完整的追蹤欄位
run_id = "BOOKRUN-2210"
plan_id = "plan-001"
command_id = "cmd-001"

# Conductor 不直接 publish,而是將指令交給 Executor 服務
# 註:以 partition_key=run_id 投遞,確保同一任務的指令與事件局部有序
command = {
    "topic": "command.signage.update.v1",
    "name": "signage.update",
    "payload": {"message": "請改走安靜帶"},
    "key": f"{run_id}-cmd-signage", # 冪等鍵
    "correlation_id": run_id,      # 追蹤整個任務
    "causation_id": plan_id        # 追蹤此指令的來源
}

# --- Executor Service (內部包含 Outbox/Relay 機制) ---
# 註:所有發布到事件總線的訊息,其消費者都應實作
# 1. 冪等性接收 (透過 key)
# 2. 帶有 backoff+jitter 的重試策略
# 3. 達到重試上限後,將訊息移至 Dead-Letter Queue (DLQ) 並觸發告警
class ExecutorService:
    def execute_and_notify(self, command: dict):
        print(f"📥 [EXECUTOR] Received command: {command['name']}")
        # 1. 原子化寫入 Outbox (此處簡化)
        print(f"📦 [OUTBOX] Saving command to outbox...")

        # 2. 執行實際動作 (呼叫 Kian 的 Tool Port)
        print(f"⚙️  Calling SignagePort with: {command['payload']['message']}")

        # 3. 執行成功後,發布「事件」
        event = {
            "topic": "events.signage.updated.v1",
            "type": "updated",
            "payload": command["payload"],
            "key": f"{run_id}-evt-signage", # 事件的冪等鍵
            "correlation_id": command["correlation_id"],
            "causation_id": command_id, # 事件的直接原因是該指令
        }
        print(f"📦 [OUTBOX] Saving event to outbox for relay...")
        print(f"📢 [EVENT BUS] Event '{event['topic']}' published.")

# --- Sable 的兩階段廣播 ---
def two_phase_broadcast(payload: dict):
    # 階段一:發布預覽事件,僅供內部審計
    preview_event = { "topic": "events.broadcast.previewed.v1", ... }
    print("👀 [SABLE] Publishing preview event for audit.")

    # ... 經過審批流程 ...
    user_approval = True # 假設審批通過

    # 階段二:發布正式提交事件,對外廣播
    if user_approval:
        committed_event = { "topic": "events.broadcast.committed.v1", ... }
        print("🚀 [SABLE] Publishing committed event to public.")

    # 若事後發現錯誤,只能發布更正事件
    # corrected_event = { "topic": "events.broadcast.corrected.v1", "supersedes": committed_event_id, ... }


# --- 執行場景 ---
if __name__ == "__main__":
    executor = ExecutorService()
    executor.execute_and_notify(command)
    two_phase_broadcast({"message": "夜跑延後10分鐘"})

7) 鄉民出題 (動手+反模式紅旗) 🚩

現在,換你來當總設計師了!

  1. 如果你是當時的英雄:在 3) 笑中帶淚 的失敗場景中,那個「超級提示詞」導致了災難。如果你是 Aster,你會如何將那個巨大的任務,拆解成至少三個可以交給不同專業代理 (例如:交通、資訊、安撫) 的 Contract-Net 標案?請寫下這三個標案的核心需求。

  2. 工具庫的擴充:假設明天城市新增了一種「無人機空中廣播」的新工具。身為 Kian (工具鍛造師),你會如何設計一個新的 DronePort,並確保它和其他 Port (如 BroadcastPort) 的介面契約是一致的,以便代理可以無痛切換?

  3. 反模式紅旗 🚩:除了文章中提到的,「代理間的閒聊 (Chattering Agents)」:代理們花費大量時間在不必要的通訊和協商上,而不是執行任務。你還能想到另一個多代理協作的「反模式」嗎?例如:「中心化獨裁者 (Centralized Dictator)」:表面上是多代理,但所有決策實質上仍由單一代理或中心節點做出,失去了去中心化的韌性與並行優勢。

8) 城市望遠鏡 (進階視野) 🔭

今天我們看到的,是多代理系統 (MAS) 在城市治理中的一個縮影。但若我們將鏡頭拉得更遠,你會發現,這正是將我們前 29 天所學的一切——從 GoF 的微觀模式到 EDA 的中觀事件流——升維為一個完整「協作語言」的最後一塊拼圖。

六角形架構的 Ports 成了代理們穩定可靠的工具庫事件總線是它們唯一的溝通渠道;SRP/OCP/LID 等 SOLID 原則,是它們之間簽訂的契約,保證了可替換性;而 Visitor、Memento、Interpreter 這些模式,則變成了代理們進行「觀測、回放、求值」的基礎設施。

https://ithelp.ithome.com.tw/upload/images/20251014/201785004ys12zpsrY.png

圖說小字:對齊你列的 DoD:一致率、P95 延遲、重複率=0、追溯性 100%。

✅ 回到現場 (驗收時刻)

22 點 10 分,Aster 的小隊輕鬆收隊。指揮中心的大螢幕上,各項指標都回到了綠色安全區。Ember 存檔了這次 run_id 的所有紀錄,並輸出了一份可供隔天複盤的報告。這次行動的成功,可以用幾項關鍵指標來衡量:

  • 人流逆向事件:在 20 分鐘內下降了 92%。

  • 三聲道一致率(看板/社群/廣播):以 SSOT 版本比對,達到 99.8%。

  • 分發延遲 P95:三管道訊息同步的端到端延遲,P95 控制在 5 秒內。

  • 重複命令率:透過冪等鍵 (key) 稽核,為 0。

  • 決策可追溯性:每一次指令與事件,都包含了 correlation_idcausation_id,審計軌跡 100% 完整。

9) 結語 & 預告

今天的核心:好的系統不是靠一個超級英雄,而是靠一套允許凡人成為英雄的協作協議。

Codetopia 的故事到此畫下一個句點,但我們的創城之旅才剛開始。感謝各位總設計師 30 天的陪伴,這座城市因為有你們的智慧而更加美好。未來,還會有更多的挑戰與冒險,我們後會有期!


附錄:ASCII 版圖示

為了確保在不支援 Mermaid 渲染的環境中也能正常閱讀,以下提供文中圖表的 ASCII 替代版本:

1. 六角架構與事件總線結構圖

    ┌─────────────────────────────────────────────────────────────────┐
    │                        DOMAIN CORE                              │
    │  ┌──────────────┐    只使用抽象 Port                           │
    │  │   Business   │    不認識 Event Bus                          │
    │  │    Logic     │◄───────────────────────┐                     │
    │  └──────────────┘                        │                     │
    └─────────────────┬───────────────────────┬─┴─────────────────────┘
                      │                       │
           ┌──────────▼──────────┐ ┌─────────▼──────────┐
           │     PORTS (抽象)     │ │     PORTS (抽象)    │
           │ • RoutePort         │ │ • SignagePort      │
           │ • BroadcastPort     │ │ • DronePort (新)   │
           └──────────┬──────────┘ └─────────┬──────────┘
                      │                      │
           ┌──────────▼──────────┐ ┌─────────▼──────────┐
           │     ADAPTERS        │ │     ADAPTERS       │
           │ • EventPublisher    │ │ • VendorSDK        │
           │ • Port 實作         │ │   Wrappers         │
           └──────────┬──────────┘ └─────────┬──────────┘
                      │                      │
                      └──────────┬───────────┘
                                 │
                    ┌────────────▼────────────┐
                    │      EVENT BUS          │
                    │   (基礎設施層)           │
                    │ • publish()             │
                    │ • subscribe()           │
                    └─────────────────────────┘

2. 事件處理流程與可靠性保證

Producer Service               Event Bus               Consumer Service
┌───────────────┐             ┌─────────┐             ┌───────────────┐
│ Command       │             │         │             │    Inbox/     │
│ Handler       │             │ Message │             │ Idempotency   │
│       │       │────────────►│ Broker  │────────────►│ Check         │
│       ▼       │             │         │             │       │       │
│ ┌───────────┐ │             │ Topic:  │             │       ▼       │
│ │  Outbox   │ │             │ events. │             │ ┌───────────┐ │
│ │ (原子化)   │ │             │ command.│             │ │  Handler  │ │
│ └─────┬─────┘ │             │         │             │ │           │ │
│       │       │             └─────────┘             │ │     │     │ │
│ ┌─────▼─────┐ │                                     │ │     ▼     │ │
│ │   Relay   │ │                成功                  │ │  Side     │ │
│ │  Process  │ │                 │                   │ │  Effect   │ │
│ └───────────┘ │                 │                   │ └─────┬─────┘ │
└───────────────┘                 │                   │       │       │
                                  │                   │       ▼       │
                                  │                   │ ┌───────────┐ │
                            重試策略 backoff+jitter       │ │  Success  │ │
                                  │                   │ └───────────┘ │
                                  │                   │               │
                                  ▼                   │    失敗時      │
                          ┌─────────────┐             │       │       │
                          │ Dead-Letter │◄────────────┤       ▼       │
                          │ Queue (DLQ) │             │ ┌───────────┐ │
                          │ + 告警機制   │             │ │  Retry    │ │
                          └─────────────┘             │ │ (上限後DLQ)│ │
                                                      │ └───────────┘ │
                                                      └───────────────┘

3. 多代理決策流程圖

Aster(Conductor) ──┐
                   │
                   ▼
         ┌─────────────────┐
         │   發出標案       │
         │ (Contract-Net)  │
         └─────────────────┘
                   │
           ┌───────┴───────┐
           ▼               ▼
  ┌─────────────┐   ┌─────────────┐
  │ Planner     │   │ 其他代理     │
  │ Agent       │   │ 投標        │
  │ 提交計畫     │   │            │
  └──────┬──────┘   └─────────────┘
         │
         ▼
  ┌─────────────┐
  │ Sable       │ ──→ 風險評估
  │ (Critic)    │ ──→ 兩階段審查
  │ 安全審查     │ ──→ Forward-Fix Only
  └──────┬──────┘
         │ (核可)
         ▼
  ┌─────────────┐      ┌──────────────┐
  │ Executor    │ ────►│   Outbox     │
  │ Agent       │      │   Service    │
  │ 執行指令     │      │              │
  └─────────────┘      └──────┬───────┘
                              │
         ┌────────────────────┘
         ▼
  ┌─────────────┐
  │ City Event  │ ──→ partition_key=run_id
  │ Bus         │ ──→ 局部有序保證
  │             │ ──→ 冪等性處理
  └─────────────┘

4. 代理團隊組織架構

                    ┌─────────────────────┐
                    │   Aster (總監)       │
                    │ • Contract-Net 招標  │
                    │ • 任務分派           │
                    └──────────┬──────────┘
                               │
            ┌──────────────────┼──────────────────┐
            │                  │                  │
    ┌───────▼───────┐  ┌──────▼──────┐  ┌────────▼────────┐
    │ Kian (工具師)  │  │ Rook (仲裁)  │  │ Sable (安全官)   │
    │ • RoutePort   │  │ • 協商衝突   │  │ • 風險審查       │
    │ • SignagePort │  │ • CUPID 權重 │  │ • 兩階段提交     │
    │ • DronePort   │  │ • 折衷決策   │  │ • Forward-Fix    │
    └───────────────┘  └─────────────┘  └─────────────────┘
                               │
                    ┌──────────▼──────────┐
                    │  Ember (記憶管家)    │
                    │ • run_id 追蹤       │
                    │ • 決策歷史記錄       │
                    │ • 可稽核快照         │
                    └─────────────────────┘
                               │
            ┌──────────────────┼──────────────────┐
            │                  │                  │
    ┌───────▼───────┐  ┌──────▼──────┐  ┌────────▼────────┐
    │ Planner       │  │ Executor    │  │ 其他專業代理     │
    │ Agent         │  │ Agent       │  │ • 交通          │
    │ • 方案規劃     │  │ • 指令執行   │  │ • 廣播          │
    │ • 策略制定     │  │ • 工具呼叫   │  │ • 資訊同步       │
    └───────────────┘  └─────────────┘  └─────────────────┘

5. 事件時間線甘特圖

BOOKRUN-2210 夜間行動時間線 (18:40 - 22:13)

時間    │18:40  19:00  19:20  19:40  20:00  20:20  20:40  21:00  21:20  21:40  22:00│
        │  │     │     │     │     │     │     │     │     │     │     │     │
天候    │▓▓▓▓▓▓▓▓▓▓毛毛雨轉中雨▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓│
人流    │                        ████████████████人流逆向高峰(P95+)████████        │
        │                                                                          │
協作    │     ■■■■■Aster招標                                                       │
節點    │                        ■■■■■■■■■■Rook仲裁(折衷方案)■■■■■■■■■■         │
        │                                                      ■■■■■■■■■■Sable兩階段│
        │                                                               ■■■SSOT同步│
        │                                                                    ■收隊  │

圖例:▓ 環境因素  ████ 問題高峰  ■ 協作行動

6. 事件結構表格

┌─────────────┬──────────────────┬────────────────────────────────────────┐
│    欄位     │      範例值      │                 說明                   │
├─────────────┼──────────────────┼────────────────────────────────────────┤
│ id          │ uuid-12345       │ 事件唯一識別                           │
│ topic       │ events.*.v1      │ 主題名稱(含版本)                       │
│ type        │ updated/created  │ 事件類型                               │
│ ts          │ 2025-10-12T19:45 │ 時間戳記                               │
│ key         │ BOOKRUN-cmd-001  │ 冪等鍵(去重複)                         │
│ correlationId│ BOOKRUN-2210    │ 追蹤整個任務                           │
│ causationId │ plan-001         │ 追蹤直接原因                           │
│ payload     │ {...}            │ 事件承載內容                           │
└─────────────┴──────────────────┴────────────────────────────────────────┘

重要約束:
✓ Schema 只增不改    ✗ 破壞性變更會被 CI 退件
✓ 新欄位可選/預設值  ✗ 不可移除既有欄位
✓ 版本語義化命名     ✗ 不可更改已發布的事件結構


上一篇
Day 29:蒼螺夜市首夜崩壞 & 事件驅動對策會議
系列文
Codetopia 新手日記:設計模式與原則的 30 天學習之旅30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言