跳转至

Event-Driven Architecture Analysis

重要性:⭐⭐⭐ 目标读者:架构师 关联analysis/architecture-history.md


1. 概览

本文档分析 Claude Code 的事件驱动架构

5 主题: - 事件类型 - 事件流 - 订阅模式 - 实践 - 改进


2. 5 大事件类型

2.1 Hook 事件

PreToolUse | PostToolUse | SessionStart | SessionEnd
Notification | Stop | SubagentStop
UserPromptSubmit | PreCompact

9 种

2.2 React 事件

useInput(input, key)  // 键盘
// Ink 事件

UI 事件

2.3 Stream 事件

type StreamEvent =
  | { type: 'message_start' }
  | { type: 'content_block_delta' }
  | { type: 'message_stop' }

API 事件

2.4 MCP 事件

notifications/progress
notifications/message
notifications/resources/updated

MCP 事件

2.5 Internal 事件

// zustand store
useAppState.subscribe(state => state.x, x => /* ... */)

内部事件


3. 事件流(5 阶段)

User 输入
  ↓ UserPromptSubmit event
Claude 处理
  ↓ content_block_delta events
Tool 调用
  ↓ PreToolUse event
  ↓ tool 执行
  ↓ PostToolUse event
Tool 结果
  ↓ content_block_delta
Stop
  ↓ Stop event

5 阶段


4. 4 种订阅模式

4.1 Pub/Sub

// 简单 pub/sub
const eventBus = new EventTarget()
eventBus.addEventListener('tool:done', handler)
eventBus.dispatchEvent(new Event('tool:done'))

basic

4.2 Observer

// zustand
useAppState.subscribe(state => state.x, x => {
  // observer
})

observer

4.3 Promise/Async

// Promise 链
eventBus.once('session:start').then(() => { ... })

promise

4.4 Stream

// Async iterator
for await (const event of stream) {
  // consume
}

stream


5. Claude Code 的事件实现

5.1 Hook 系统

// 9 事件
type HookEventName = 'PreToolUse' | ...

// settings.json
{
  "hooks": {
    "PreToolUse": [
      { "matcher": "Bash", "hooks": [...] }
    ]
  }
}

JSON 配置

5.2 React + Ink 事件

useInput((input, key) => {
  if (key.return) handleSubmit()
  if (input === 'q') handleQuit()
})

useInput

5.3 API Stream

const stream = await client.messages.create({ stream: true })
for await (const event of stream) {
  // 5 种事件
}

5 事件

5.4 MCP Progress

await server.notification({
  method: 'notifications/progress',
  params: { progressToken, progress, total }
})

progress

5.5 zustand Store

useAppState.subscribe(
  state => state.verbose,
  (verbose) => { /* observer */ }
)

zustand


6. 5 个关键设计

6.1 Hook 解耦

// 业务 + 生命周期解耦

decouple

6.2 Stream 异步迭代

// async iterator 自然适配 stream

natural

6.3 zustand 精确订阅

useAppState(s => s.field)  // 只订阅 field

precise

6.4 Event bus 全局

// 推测
// utils/events.ts
const eventBus = new EventEmitter()

global

6.5 Notification 协议

// MCP standard
notifications/*

standard


7. 5 个优点

7.1 解耦

// 业务不关心 lifecycle

decouple

7.2 可扩展

// 加新 hook 不改 core

extensible

7.3 异步

// async 友好

async

7.4 跨进程

// MCP 可跨进程

cross

7.5 类型安全

// TS type event payload

typed


8. 5 个缺点

8.1 难调试

// 异步事件流难 trace

debug

8.2 内存泄漏

// listener 不释放

leak

8.3 顺序

// 异步事件顺序不保证

order

8.4 错误处理

// handler 抛错会怎样?

error

8.5 测试

// 异步事件难测

test


9. 5 个常见模式

9.1 Event Emitter

class EventEmitter {
  on(event, handler) { ... }
  emit(event, data) { ... }
}

EE

9.2 Promise 链

await new Promise(r => {
  eventBus.once('ready', r)
})

promise

9.3 Async Iterator

for await (const event of stream) { ... }

iterator

9.4 Subject (RxJS)

const subject = new Subject<Event>()
subject.next(event)
subject.subscribe(handler)

RxJS

9.5 Emittery

// npm package
import Emittery from 'emittery'
const ee = new Emittery()
ee.on('event', handler)
await ee.emit('event', data)

emittery


10. 5 个 Claude Code 模式

10.1 Hook 模式

// settings.json 配置 → 触发 shell

config-driven

10.2 useInput 模式

// 集中处理键盘

centralized

10.3 Stream 模式

// API stream

stream

10.4 zustand 模式

// 状态订阅

state

10.5 Notification 模式

// MCP 推送

push


11. 5 个最佳实践

11.1 小事件

// 小 payload

small

11.2 类型化

// typed event payload

typed

11.3 命名

// namespace:action
tool:start, tool:done

命名

11.4 unsubscribe

// 记得 unsubscribe

cleanup

11.5 错误隔离

// try/catch in handler

isolated


12. 5 个改进方向

12.1 统一事件总线

// 内部 + 外部 统一

unified

12.2 TypeScript discriminated union

type Event =
  | { type: 'tool:start'; tool: string }
  | { type: 'tool:done'; tool: string; result: any }

discriminated

12.3 Event sourcing

// 所有事件持久化

sourcing

12.4 Reactive stream

// RxJS / xstream

reactive

12.5 Event bus + WebSocket

// 跨进程

bus


13. 5 个事件流案例

13.1 Tool 调用流

PreToolUse
Tool 执行
PostToolUse
content_block_delta
Stop

tool

13.2 Session 启动流

SessionStart
UserPromptSubmit
content_block_delta (× N)
Stop

session

13.3 MCP 连接流

initialize
initialized
tools/list
tools/call
notifications/progress (多次)

mcp

13.4 Subagent 流

SubagentStart (推测)
Subagent (Agent tool)
SubagentStop

subagent

13.5 Compact 流

PreCompact
Compact
PostCompact (推测)

compact


14. 5 个 trade-off

同步  ↔  异步
推  ↔  拉
全局  ↔  局部
类型  ↔  灵活
简单  ↔  强大

5 维 trade-off


15. 总结

Event-Driven Architecture = 5 事件类型 + 4 订阅模式

核心: - 9 hook 事件 - 5 API stream 事件 - zustand 订阅 - MCP notifications - 5 模式

下一步: - 看 architecture-history.md - 统一事件总线 - 类型化