異なるコンテキスト間での整合性
TL;DR
異なる 境界づけられたコンテキスト 間は メッセージ(ドメインイベント)を使って 非同期 にやり取りする
このとき、 整合性 は 結果整合性 である
つまり、整合性 が有効になるのはある程度の時間が経ってからである
hr.icon
異なるコンテキスト間で 整合性 を担保するにはどうすれば良いか
注文が確定すると、それに対応する請求書が必ず作成される
請求書の発行は、「受注」ドメインではなく「請求」ドメインの一部
それぞれ 境界づけられたコンテキスト で分離されているため、境界を超えてオブジェクトを操作できない
請求コンテキストにパブリックな API を用意して、以下のようにする
code:text
Ask billing context to create invoice
if successfully created:
create order is order-taking context
どちらかのアップデートが失敗した場合を考慮する必要があり複雑
別々のシステム間で更新を適切に同期させる方法(2フェーズコミット)もあるが、必要になることはない
必要になることはない
実世界において、サブシステムが1 つのステージを終えるのを待ってから次のステージに移ることはない
スターバックスは2フェーズコミットを使わない
代わりに、メッセージ(イベント) を使って 非同期 に調整を行う
稀にうまくいかないこともあるが、稀なエラーに対処するコストは、すべてを同期させるコストよりも遥かに少ないことが多い(らしい)radish-miyazaki.icon
e.g. 請求書の作成をすぐに要求するのではなく、請求ドメインにメッセージ(イベント)を送信し、残りの注文処理を続行する
メッセージが失われた場合どうするか?
1. 何もしない
顧客は無料で商品を手に入れ、企業はコストを計上する
コストが小さい場合は、適切な解決方法
2. メッセージが失われたことを検知して再送信
どう検知する?
受信側と送信側の 2 つのデータを比較し、一致しない場合はエラーとする
3. 前のアクションを「元に戻す」またはエラーを修正する 補償アクション を作成する
イベントソーシング と関連している ?? radish-miyazaki.icon
注文をキャンセルして顧客に商品を送り返すように求めたり、返金したりする
整合性 が求められる場合は 2 か 3 を選択する必要がある
この場合、整合性 が有効になるのはある程度の時間が経ってから
?? radish-miyazaki.icon
結果整合性
e.g. 商品の価格が変更されていない場合、まだ発送されていないすべての注文を更新する
すぐに整合性を取る必要がある場合
商品レコードの各行を変更する際に、影響を受け取るすべての注文も更新する必要があり時間がかかる
すぐに整合性を取る必要がない場合
「価格が変更された(PriceChanged)」ドメインイベントを作成する
このイベントが、「変更済みの価格で注文を更新する(UpdateOrderWithChangePrice)」コマンド のトリガーとなる
このコマンドは、商品の価格が変更されてから、しばらくして処理される