イベントソーシングを使用して簡単なショッピングシナリオをプログラムしようとしています。
--------------- --------------- ----------------
| OrderService | | ProductService | | PaymentService |
---------------- ------------------ -----------------
|________________|_____________________|
|
--------------------
| KAFKA |
--------------------
|
--------------------
| PROCESSOR |
--------------------
|
--------------------
| DATABASE |
--------------------
3つのサービスがあります。
Kafka:さまざまなイベントのイベントストア。
Processor:現在の状態のビューを生成するCQRSプロセッサ。
データベース:現在の状態のマテリアライズドビュー。
私の主な疑問は、次のようなフローにどのように対処するかです。
純粋なイベントソーシングアプローチであるため、ProductServiceにはデータベースがありません。
私の頭に浮かぶ問題のあるケース:
このようなシナリオを処理するための推奨される方法は何ですか?
ここにあるのは、複数のサービスを生成するプロセスです。 [〜#〜] ddd [〜#〜] では、これらのサービスは可能な最大のトランザクション境界である集約です。 DDDとの関連で答えます。
これは、注文プロセスをorder placed
からorder completed
イベントに調整する Saga/Process manager (OrderProcess
)でモデル化できます。
ProductServiceは商品の在庫を確認し、それに基づいてProductReservedまたはOrderCancelledNoStockイベントを作成します。
実際、ProductService
はProductReserved
イベントを発生させますが、OrderCancelledNoStock
イベントは発生させません。このサービスは注文について知る必要はなく、product reserving
-懸念の分離についてのみ知っている必要があります。代わりに、ProductOutOfStock
例外をスローする必要があります。
ProductReserved
イベントが発生した場合、OrderProcess
はそれを受け取り、PaymentService
にコマンドを送信して支払いを行います(これは実際の支払い手順によって異なります)。
ProductOutOfStock
例外がスローされた場合、OrderProcess
はそれをキャッチしてCancelOrder
をOrderService
に送信します。
同じ製品の2つの同時OrderPlacedがProductServiceに到着します。これはDATABASEを呼び出して、製品の在庫があるかどうかを確認します(残り1製品)。どちらも問題ないので、同じ製品に対してProductReservedイベントを作成し、PaymenServiceがそれを処理します。
OrderService
は、イベントソースの集約として実装されている場合、すべての製品が予約された後にProductOutOfStock
例外をスローすることで許可されません。在庫の検証は、予測ではなく、以前に生成されたイベントのストリーム全体に対して行われます。同時コマンド実行の場合、イベントを永続化しようとする最後のコマンドはそれらを永続化することに失敗し、その後、イベントはallを再ロードすることによって再試行されます、winingコマンドによって生成されたものを含め、ProductOutOfStock
例外で失敗します。
一般的な規則として、コマンドの検証は常にプリンシパルストレージ(イベントストリーム)に対して行われる必要があります。そうでない場合、最終的に一貫した予測に対して検証すると、正しく指摘したように、一貫性が失われる可能性があります。
場合によっては、2つのステップで検証することが理にかなっていることがあります。最初は予測に対して、次に主ストレージに対してです。たとえば、UIはデータベースにクエリを実行して、在庫がゼロの場合に「在庫切れ」メッセージをユーザーに表示します。しかし、ユーザーが注文すると、バックエンドはイベントストリームに対してそれを検証します。