CQRS / ESでは、コマンドは別のコマンドを作成できますか?


10

CQRS / ESでは、コマンドはクライアントからサーバーに送信され、適切なコマンドハンドラーにルーティングされます。そのコマンドハンドラーは、リポジトリーからアグリゲートをロードし、その上のいくつかのメソッドを呼び出して、それをリポジトリーに保存します。イベントが生成されます。イベントハンドラー/佐賀/プロセスマネージャーは、コマンドを発行するためにこれらのイベントをリッスンできます。

そのため、コマンド(入力)はイベント(出力)を生成し、それがシステムにさらにコマンド(入力)をフィードバックできます。さて、コマンドがイベントを発行せず、別のコマンドをエンキューするのが一般的な方法でしょうか?このようなアプローチは、外部プロセスでの実行を強制するために使用できます。

編集:

私が考えている特定のユースケースは、支払いの詳細の処理です。クライアントはPayInvoiceコマンドを送信します。そのペイロードにはユーザーのクレジットカードの詳細が含まれます。PayInvoiceHandler通過MakeInvoicePayment支払いゲートウェイとの相互作用の原因である別のプロセスにコマンドを。支払いが成功すると、InvoicePaidイベントが生成されます。PayInvoiceコマンドが保持された後、コマンドが保持される前に何らかの理由でシステムがクラッシュした場合MakeInvoicePaymentは、これを手動で追跡できます(支払いは行われません)。MakeInvoicePaymentコマンドが持続した後、システムがクラッシュする前にInvoicePaidイベントが持続する場合、ユーザーのクレジットカードに請求が行われているのに、請求書に支払い済みのフラグが付けられていない可能性があります。その場合、状況を手動で調査し、請求書に手動で支払い済みのマークを付ける必要があります。

回答:


11

振り返ってみると、問題を複雑にしていたと思います。

一般に、コマンドは例外をスローするか、1つ以上のイベントを発生させる必要があります。

イベントソーシングのアーキテクチャを要約すると、次のようになります。

  • コマンドは、何かをするための指示を表す入力です。
  • イベントは、行われたことの歴史的事実を表す出力です。
  • イベントハンドラーは、コマンドを発行するためにイベントをリッスンして、システムのさまざまな部分を調整することができます。

あるコマンドが別のコマンドを作成すると、コマンドとイベントの一般的な意味が曖昧になります。あるコマンドが別のコマンドを「トリガー」する場合、そのコマンドは「行われたことの歴史的事実」であることを意味します。これは、これらの2種類のメッセージの意図と矛盾し、他の開発者がイベントからイベントをトリガーする可能性があり、データの破損や最終的な不整合につながる可能性があるという点で、滑りやすい経路になる可能性があります。

私が提起した特定のシナリオに関して、複雑な要因は、メインスレッドが支払いゲートウェイと対話することを望まないことでした(これは、永続的なシングルスレッドプロセスであるため)、他のコマンドを処理できないためです。 。ここでの簡単な解決策は、支払いを処理する別のスレッド/プロセスを生成することです。

説明のために、クライアントはPayInvoiceコマンドを送信します。PayInvoiceHandler新しいプロセスを開始し、それに支払いの詳細を渡します。新しいプロセスは支払いゲートウェイと通信します。支払いが成功した場合はinvoice.markAsPaid()、レシート番号(InvoicePaidイベントを生成する)を使用して呼び出します。支払いが失敗した場合はinvoice.paymentFailed()、詳細な調査(InvoicePaymentFailedイベントを生成)のために参照コードを渡して呼び出します。したがって、別のプロセス/スレッドが関係しているという事実にもかかわらず、パターンは残りCommand -> Eventます。

失敗に関しては、3つのシナリオがあり、PayInvoiceコマンドが持続した後、InvoicePaidまたはInvoicePaymentFailedイベントが持続する前に、システムがクラッシュする可能性があります。この場合、ユーザーのクレジットカードに請求されたかどうかはわかりません。このような場合、ユーザーはクレジットカードの請求に気づき、苦情を申し立てます。その場合、スタッフメンバーが問題を調査し、請求書に支払い済みのマークを手動で付けることができます。


1
質問と回答の両方に感謝します。全体として、混乱する点がいくつかあります。(1)多くの人がイベントハンドラーの概念について話しているのを見たことはありません。(2)あなたの見解の私の解釈は、作業の大部分をイベントハンドラーに移し、コマンドハンドラーが純粋な変換関数になり、コマンド/イベントへの分離がさらに必要かどうかという疑問を投げかけます。興味がある場合は、次の質問を参照してください。
bluenote10

3

コマンドからイベントを発行するだけの場合、アーキテクチャ的にはより疎結合なシステムになります。別の言い方をすれば、1つのコマンドが他に発行する外部コマンドを認識する必要はありません。これは外部の当事者の責任である必要があります(イベントにサブスクライブする必要があり、先に述べたように、調整の責任を持つ佐賀マネージャー、またはこれらのイベントに依存する別のモジュールにすぎません)。


2

推奨される表示:信頼性のあるメッセージングに関するUdi Dahan- それはあなたが説明しているものとはまったく異なりますが、密接に関連しています。

さて、コマンドがイベントを発行せず、別のコマンドをエンキューするのが一般的な方法でしょうか?

私はそのようなやり方を勧める人を見たことがありません。

短い答え:状態を保存しないと、エンキューされたコマンドを受け取ったことを確認した後でクラッシュした場合、エンキューされたコマンドを回復できません。

状態を保存する必要があると判断した場合、イベントハンドラーを使用するのではなく、最初のコマンドから2番目のコマンドをスケジュールすることには大きな利点があることは明らかではありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.