event-driven-messaging について
Event-Driven Messagingは、イベント駆動システムを設計する開発者向けの手引きです。イベント契約、永続化後の発行、冪等なコンシューマー、回数を制限した再試行、統合テストを扱います。
主な機能
- 01不変でバージョン付きのイベントエンベロープを定義
- 02状態の永続化後にイベントを発行
- 03Outboxでデータベースとブローカーの書き込みを調整
- 04コンシューマーを冪等にする
- 05再試行を制限し不正メッセージを振り分け
- 06互換性と配信時のエッジケースをテスト
活用シーン
- 01進化するサービスのイベントスキーマを設計
- 02コンシューマーによる重複処理を防止
- 03一時的・恒久的なメッセージ障害に対応
- 04順序変更・遅延・不正メッセージをテスト
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ rrezartprebreza/ spring-boot-skills --skill event-driven-messagingインストール後、Claude Code で/event-driven-messagingを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
agents/openai.yamlexamples/bad-consumer.javagood-consumer.java詳細
イベント駆動型メッセージング
システム全体でより強いセマンティクスが保証されない限り、少なくとも1回の配信を前提に設計してください。
イベントコントラクト
eventId、eventType、occurredAt、schemaVersion、およびペイロードを含む、不変のイベントエンベロープを使用してください。- 公開済みのスキーマは API として扱ってください。フィールドは互換性を保って追加し、意味を予告なく変更しないでください。
- 相関 ID と原因 ID はヘッダーまたはエンベロープに格納してください。
- JPA エンティティやフレームワーク固有のシリアライズ形式を公開しないでください。
プロデューサーのルール
- 元となる状態変更が永続化された後にのみ公開してください。
- データベースの状態とブローカーへの公開を一致させる必要がある場合は、トランザクショナルアウトボックスを使用してください。
- 集約ごとの順序が重要な場合は、決定的なパーティションキーを使用してください。
- 配信タイムアウトと確認応答を明示的に設定してください。
コンシューマーのルール
- 永続的な処理済みイベントの記録、または自然に冪等な書き込みを使って、ハンドラーを冪等にしてください。
- 状態変更と冪等性マーカーを含むようにトランザクション境界を設定してください。
- リトライを設定する前に、一時的な障害と恒久的な障害を分類してください。
- バックオフを使ってリトライ回数に上限を設け、その後、処理不能なメッセージをデッドレターの送信先にルーティングしてください。
- 再生に備えて、元のイベント、失敗の理由、試行回数を保持してください。
テスト
- シリアライズの互換性とハンドラーの冪等性をテストしてください。
- ブローカーの統合テストには Testcontainers を使用してください。
- 重複したメッセージ、順序が入れ替わったメッセージ、遅延したメッセージ、処理不能なメッセージをテストしてください。
例
examples/good-consumer.javaとexamples/bad-consumer.javaを参照してください。
注意点
- エージェントはブローカーがトランザクションをサポートしているため、厳密に1回だけ配信されると想定します。エンドツーエンドの副作用には、依然として冪等性が必要です。
- エージェントは検証エラーを無期限にリトライします。恒久的な障害は速やかにデッドレターに送ってください。
- エージェントはアウトボックスを使わずにデータベーストランザクション内でイベントを公開します。クラッシュによって状態とイベント配信が分離する可能性があります。
- エージェントはランダムなパーティションキーを使います。その結果、1つの集約に対する順序が失われます。
- エージェントは JPA エンティティに直接デシリアライズします。バージョン管理されたイベントコントラクトを使用してください。
コメント
Markdown 対応