iii-event-driven-cqrs について
iii-event-driven-cqrsは、iiiエンジンでイベント駆動型CQRSとイベントソーシングのパターンを実装するスキルです。コマンド処理、イベント発行、独立した読み取りプロジェクション、クエリとコマンド用のHTTPエンドポイントを説明します。
主な機能
- 01コマンドとクエリの責務分離
- 02順序付き状態ログへのイベント追記
- 03イベント発行による購読者への配信
- 04独立したクエリプロジェクションの構築
- 05コマンド・クエリ用HTTPエンドポイント
活用シーン
- 01在庫変更をドメインイベントとしてモデル化
- 02共有イベントから一覧・集計プロジェクションを維持
- 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 がファンアウトを処理します。1つのイベントがすべてのプロジェクションと下流のコンシューマーに届きます
- 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 | ワーカーを初期化し、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 })— ワーカーの初期化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()
このパターンの適用
タスクに当てはまる場合は、以下の適用方法を使用してください。
- 既存のイベントトピックに購読トリガーを登録して、新しいプロジェクションを追加します
- プロジェクションごとに個別の状態スコープを使用します(例:
inventory-list、inventory-stats) - コマンドは発行前に検証し、無効なコマンドは早期に拒否します
- 重要なイベント処理では、確実に配信するために PubSub の代わりに
TriggerAction.Enqueue({ queue })を使用します - イベント ID は、順序を保てるよう一意かつ単調増加にします(例:
evt-${Date.now()}-${counter})
パターンの境界
- リアクティブな副作用を伴う単純な CRUD がタスクの場合は、
iii-reactive-backendを優先してください。 - 再試行可能な永続的な複数ステップのパイプラインが必要なタスクの場合は、
iii-workflow-orchestrationを優先してください。 - コマンドとクエリの分離、イベントソーシング、独立したプロジェクションが主な関心事の場合は、
iii-event-driven-cqrsを使用してください。
使用する場面
- タスクの主な内容が、iii エンジンにおける
iii-event-driven-cqrsである場合に、このスキルを使用してください。 - リクエストでこのパターン、または同等の実装が直接求められた場合に適用します。
適用範囲
- 無関係なタスクに対する汎用的なフォールバックとして、このスキルを使用しないでください。
- より適切な iii スキルがある場合、このスキルを適用してはいけません。
- このスキルの例を適用する前に、必ず環境と安全上の制約を確認してください。
コメント
Markdown 対応