CQRS/ESでは、コマンドはクライアントからサーバーに送信され、適切なコマンドハンドラーにルーティングされます。そのコマンドハンドラーは、そのリポジトリーから集約をロードし、その上のいくつかのメソッドを呼び出して、それをリポジトリーに保存します。イベントが生成されます。イベントハンドラー/佐賀/プロセスマネージャーは、コマンドを発行するためにこれらのイベントをリッスンできます。
そのため、コマンド(入力)はイベント(出力)を生成し、さらに多くのコマンド(入力)をシステムにフィードバックできます。さて、コマンドがイベントを発行せずに、別のコマンドをエンキューするのは一般的な習慣ですか?このようなアプローチは、外部プロセスでの実行を強制するために使用できます。
編集:
私が考えている特定のユースケースは、支払いの詳細の処理です。クライアントはPayInvoice
コマンドを送信します。そのペイロードにはユーザーのクレジットカードの詳細が含まれます。 PayInvoiceHandler
は、MakeInvoicePayment
コマンドを別のプロセスに渡します。このプロセスは、支払いゲートウェイとの対話を担当します。支払いが成功すると、InvoicePaid
イベントが生成されます。何らかの理由でPayInvoice
コマンドが保持された後、MakeInvoicePayment
コマンドが保持される前にシステムがクラッシュした場合、これを手動で追跡できます(支払いは行われません)。 MakeInvoicePayment
コマンドが保持された後、InvoicePaid
イベントが保持される前にシステムがクラッシュした場合、ユーザーのクレジットカードに請求が行われているが、請求書に支払い済みのフラグが付けられていない可能性があります。 。その場合、状況を手動で調査し、請求書に手動で支払い済みのマークを付ける必要があります。
振り返ってみると、私は問題を複雑にしていたと思います。
一般に、コマンドは例外をスローするか、1つ以上のイベントを発生させる必要があります。
イベントソーシングのアーキテクチャを要約すると、次のようになります。
あるコマンドが別のコマンドを作成すると、コマンドとイベントの一般的な意味が曖昧になります。あるコマンドが別のコマンドを「トリガー」する場合、そのコマンドは「行われたことの歴史的事実」であることを意味します。これはこれら2つのタイプのメッセージの意図と矛盾し、他の開発者がイベントからイベントをトリガーし、データの破損や最終的にinconsistencyにつながる可能性があるという点で、滑りやすい経路になる可能性があります。
私が提起した特定のシナリオに関して、複雑な要因は、メインスレッドが支払いゲートウェイと対話することを望まないことでした(これは、永続的なシングルスレッドプロセスであるため)、他のコマンドを処理できないためです。 。ここでの簡単な解決策は、別のスレッド/プロセスを生成して支払いを処理することです。
説明のために、クライアントはPayInvoice
コマンドを送信します。 PayInvoiceHandler
は新しいプロセスを開始し、支払いの詳細を渡します。新しいプロセスは支払いゲートウェイと通信します。支払いが成功した場合は、領収書番号(InvoicePaid
イベントを生成)を使用してinvoice.markAsPaid()
を呼び出します。支払いが失敗した場合、さらに調査するための参照コードを渡してinvoice.paymentFailed()
を呼び出します(これによりInvoicePaymentFailed
イベントが生成されます)。したがって、別のプロセス/スレッドが関係しているという事実にもかかわらず、パターンはCommand -> Event
のままです。
失敗に関しては、3つのシナリオがあり、PayInvoice
コマンドが持続した後、InvoicePaid
またはInvoicePaymentFailed
イベントが持続する前に、システムがクラッシュする可能性があります。この場合、ユーザーのクレジットカードに請求されたかどうかはわかりません。このような場合、ユーザーはクレジットカードの請求に気づき、苦情を申し立てます。その場合、スタッフメンバーが問題を調査し、手動で請求書に支払い済みのマークを付けることができます。
コマンドからイベントを発行するだけの場合、アーキテクチャ的にはより疎結合なシステムになります。別の言い方をすれば、1つのコマンドが他に発行する外部コマンドを認識する必要はありません。これは外部の当事者の責任である必要があります(イベントにサブスクライブする必要があり、先に述べたように、調整の責任を持つ佐賀マネージャー、またはこれらのイベントに依存する別のモジュールのみが考えられます)。
推奨される表示: Reliable Messaging -のUdi Dahan-これは、あなたが説明しているものとはまったく異なりますが、密接に関連しています。
さて、コマンドがイベントを発行せず、別のコマンドをエンキューするのは一般的な慣行ですか?
私はそのようなやり方を勧める人を見たことがありません。
短い答え:状態を保存しないと、エンキューされたコマンドを受け取ったことを確認した後でクラッシュした場合、エンキューされたコマンドを回復できません。
状態を保存する必要があると判断した場合、イベントハンドラーを使用するのではなく、最初から2番目のコマンドをスケジュールすることには大きな利点があることは明らかではありません。