iii-event-driven-cqrs
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseEvent-Driven CQRS & Event Sourcing
事件驱动型CQRS与事件溯源
Comparable to: Kafka, RabbitMQ, CQRS/Event Sourcing systems
同类技术:Kafka、RabbitMQ、CQRS/事件溯源系统
Key Concepts
核心概念
Use the concepts below when they fit the task. Not every CQRS system needs all of them.
- Write side: Commands validate input and publish domain events via pubsub
- Read side: Multiple projections subscribe to events independently, building query-optimized views in state
- Event log: Events are appended to state as an ordered log (event sourcing)
- PubSub handles fan-out — one event reaches all projections and downstream consumers
- HTTP triggers expose both command endpoints (POST) and query endpoints (GET)
当任务符合以下场景时使用这些概念,并非所有CQRS系统都需要全部概念。
- 写入端:命令验证输入并通过pubsub发布领域事件
- 读取端:多个投影独立订阅事件,在状态中构建查询优化视图
- 事件日志:事件以有序日志的形式追加到状态中(事件溯源)
- PubSub 处理扇出——单个事件可送达所有投影和下游消费者
- HTTP触发器 同时暴露命令端点(POST)和查询端点(GET)
Architecture
架构
text
HTTP POST /inventory (command)
→ cmd::add-inventory-item → validate → append event to state
→ publish('inventory.item-added')
↓ (fan-out via subscribe triggers)
→ proj::inventory-list (updates queryable list view)
→ proj::inventory-stats (updates aggregate counters)
→ notify::inventory-alert (sends low-stock alerts)
HTTP GET /inventory (query)
→ query::list-inventory → reads from projection statetext
HTTP POST /inventory (command)
→ cmd::add-inventory-item → validate → append event to state
→ publish('inventory.item-added')
↓ (fan-out via subscribe triggers)
→ proj::inventory-list (updates queryable list view)
→ proj::inventory-stats (updates aggregate counters)
→ notify::inventory-alert (sends low-stock alerts)
HTTP GET /inventory (query)
→ query::list-inventory → reads from projection stateiii Primitives Used
使用的iii原语
| Primitive | Purpose |
|---|---|
| Initialize the worker and connect to iii |
| Define commands, projections, and queries |
| Event log and projection state |
| Publish domain events |
| Subscribe projections to events |
| Command and query endpoints |
| Fire-and-forget notifications |
| 原语 | 用途 |
|---|---|
| 初始化worker并连接到iii |
| 定义命令、投影和查询 |
| 事件日志和投影状态 |
| 发布领域事件 |
| 订阅事件的投影 |
| 命令和查询端点 |
| 即发即弃的通知 |
Reference Implementation
参考实现
See ../references/event-driven-cqrs.js for the full working example — an inventory management system
with commands that publish domain events and multiple projections building query-optimized views.
查看../references/event-driven-cqrs.js获取完整的工作示例——一个库存管理系统,其中命令会发布领域事件,多个投影构建查询优化视图。
Common Patterns
常见模式
Code using this pattern commonly includes, when relevant:
- — worker initialization
registerWorker(url, { workerName }) - — event log append
trigger({ function_id: 'state::set', payload: { scope: 'events', key, value } }) - — domain event publishing
trigger({ function_id: 'publish', payload: { topic, data } }) - — projection subscriptions
registerTrigger({ type: 'subscribe', function_id, config: { topic } }) - Command functions with prefix, projection functions with
cmd::prefix, query functions withproj::prefixquery:: - Multiple projections subscribing to the same topic independently
- — structured logging per command/projection
const logger = new Logger()
使用此模式的代码通常包含以下内容(相关时):
- —— worker初始化
registerWorker(url, { workerName }) - —— 事件日志追加
trigger({ function_id: 'state::set', payload: { scope: 'events', key, value } }) - —— 领域事件发布
trigger({ function_id: 'publish', payload: { topic, data } }) - —— 投影订阅
registerTrigger({ type: 'subscribe', function_id, config: { topic } }) - 命令函数使用前缀,投影函数使用
cmd::前缀,查询函数使用proj::前缀query:: - 多个投影独立订阅同一主题
- —— 每个命令/投影的结构化日志
const logger = new Logger()
Adapting This Pattern
模式适配
Use the adaptations below when they apply to the task.
- Add new projections by registering subscribe triggers on existing event topics
- Use separate state scopes for each projection (e.g. ,
inventory-list)inventory-stats - Commands should validate before publishing — reject invalid commands early
- For critical event processing, use instead of pubsub for guaranteed delivery
TriggerAction.Enqueue({ queue }) - Event IDs should be unique and monotonic for ordering (e.g. )
evt-${Date.now()}-${counter}
当以下情况适用于任务时,进行相应适配:
- 通过在现有事件主题上注册订阅触发器来添加新投影
- 为每个投影使用单独的状态作用域(例如、
inventory-list)inventory-stats - 命令应在发布前进行验证——尽早拒绝无效命令
- 对于关键事件处理,使用替代pubsub以保证交付
TriggerAction.Enqueue({ queue }) - 事件ID应唯一且单调递增以保证顺序(例如)
evt-${Date.now()}-${counter}
Pattern Boundaries
模式适用边界
- If the task is about simple CRUD with reactive side effects, prefer .
iii-reactive-backend - If the task needs durable multi-step pipelines with retries, prefer .
iii-workflow-orchestration - Stay with when command/query separation, event sourcing, and independent projections are the primary concerns.
iii-event-driven-cqrs
- 如果任务是带有反应式副作用的简单CRUD操作,优先使用。
iii-reactive-backend - 如果任务需要带重试机制的持久化多步骤流水线,优先使用。
iii-workflow-orchestration - 当命令/查询分离、事件溯源和独立投影是主要需求时,选择。
iii-event-driven-cqrs
When to Use
适用场景
- Use this skill when the task is primarily about in the iii engine.
iii-event-driven-cqrs - Triggers when the request directly asks for this pattern or an equivalent implementation.
- 当任务主要涉及在iii引擎中使用时,使用此技能。
iii-event-driven-cqrs - 当请求直接要求此模式或等效实现时触发。
Boundaries
使用限制
- Never use this skill as a generic fallback for unrelated tasks.
- You must not apply this skill when a more specific iii skill is a better fit.
- Always verify environment and safety constraints before applying examples from this skill.
- 切勿将此技能作为无关任务的通用 fallback。
- 当更特定的iii技能更合适时,不得应用此技能。
- 在应用此技能中的示例前,始终验证环境和安全约束。