mcpField
I
iii-event-driven-cqrs

iii-event-driven-cqrs

github.com/iii-hq开发222 次安装
代码仓库

关于 iii-event-driven-cqrs

iii-event-driven-cqrs 是一项技能,用于在 iii 引擎中实现事件驱动的 CQRS 与事件溯源模式。它介绍命令处理、事件发布、独立读取投影,以及用于查询和命令的 HTTP 端点。

主要功能

  1. 01分离命令与查询职责
  2. 02将事件追加到有序状态日志
  3. 03发布事件并扇出至订阅者
  4. 04构建独立的查询投影
  5. 05提供命令和查询 HTTP 端点

适用场景

  1. 01将库存变更建模为领域事件
  2. 02根据共享事件维护列表和聚合投影
  3. 03为现有事件流添加订阅者或投影

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/iii-hq/skills --skill iii-event-driven-cqrs

安装后在 Claude Code 中输入/iii-event-driven-cqrs确认已加载。

详细介绍

事件驱动的 CQRS 与事件溯源

可与以下系统相比较:Kafka、RabbitMQ、CQRS/事件溯源系统

核心概念

在适合任务的情况下使用以下概念。并非所有 CQRS 系统都需要包含这些概念。

  • 写入端:命令验证输入,并通过 pubsub 发布领域事件
  • 读取端:多个投影分别订阅事件,在状态中构建针对查询优化的视图
  • 事件日志:事件以有序日志的形式追加到状态中(事件溯源)
  • PubSub 负责扇出——一个事件会传递到所有投影和下游消费者
  • HTTP 触发器同时公开命令端点(POST)和查询端点(GET)

架构

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 state

使用的 iii 原语

原语用途
registerWorker初始化 worker 并连接到 iii
registerFunction定义命令、投影和查询
trigger({ function_id: 'state::set/get/list', payload })事件日志和投影状态
trigger({ function_id: 'publish', payload })发布领域事件
registerTrigger({ type: 'subscribe', config: { topic } })订阅事件的投影
registerTrigger({ type: 'http' })命令和查询端点
trigger({ ..., action: TriggerAction.Void() })即发即弃通知

参考实现

完整可运行示例见 ../references/event-driven-cqrs.js:这是一个库存管理系统,其中的命令会发布领域事件,多个投影会构建针对查询优化的视图。

常见模式

采用此模式的代码通常会根据需要包含以下内容:

  • registerWorker(url, { workerName }) — worker 初始化
  • 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:: 前缀
  • 多个投影分别订阅同一个 topic
  • const logger = new Logger() — 对每个命令/投影进行结构化日志记录

调整此模式

在适用于任务的情况下使用以下调整方式。

  • 在现有事件 topic 上注册订阅触发器,以添加新投影
  • 为每个投影使用单独的状态作用域(例如 inventory-list、inventory-stats)
  • 命令应在发布前进行验证——尽早拒绝无效命令
  • 对于关键事件处理,使用 TriggerAction.Enqueue({ queue }) 替代 pubsub,以确保消息送达
  • 事件 ID 应唯一且单调递增,以保证顺序(例如 evt-${Date.now()}-${counter})

模式边界

  • 如果任务涉及带有响应式副作用的简单 CRUD,请优先使用 iii-reactive-backend。
  • 如果任务需要可重试的持久化多步流水线,请优先使用 iii-workflow-orchestration。
  • 当命令/查询分离、事件溯源和独立投影是主要关注点时,继续使用 iii-event-driven-cqrs。

适用场景

  • 当任务主要涉及 iii 引擎中的 iii-event-driven-cqrs 时,使用此技能。
  • 当请求直接要求使用此模式或实现等效方案时触发。

边界

  • 切勿将此技能用作无关任务的通用回退方案。
  • 如果有更具体的 iii 技能更适合,就不得使用此技能。
  • 应用此技能中的示例前,务必先确认环境和安全约束。

评论

支持 Markdown