背景
事実
・複数のマイクロサービスが連携するケース
・複数のシステムが連携するシステムオブシステムズのようなケース
では、たとえ境界付けられたコンテキストで論理的にコンポーネントを切り分けていても、
そのコンポーネントの数が多いほど、結果整合しないといけないコンポーネント数も増え、
エラー発生時による補償トランザクションが何度も走りやすくなりやすい。
問い
その結果、サービスとしての体験品質低下につながりやすいのではないか?
これを解消するための策としてどのようなものがあるだろうか?
では、以下にそのUI/UXの体験品質を損なわないようにするためのいくつかの方法を列挙します。
1. フロントでの同期的な事前検証
全ての処理を非同期のサーガに任せるのではなく、
失敗する可能性が最も高い、あるいは
ビジネス上最もクリティカルな検証 だけは、プロセスの開始前に同期的に行います。
目的
明らかに失敗するトランザクションを、サーガが開始される前に弾くことで、無駄な補償トランザクションの発生を大幅に減らします。
具体例
ECサイトの注文処理で、サーガを開始する前に、
在庫の引き当て可否のチェック
決済手段(クレジットカード)の有効性の簡易チェック
だけをまず同期的に行い、パスした場合にのみ「注文を受け付けました」と応答し、非同期のサーガ(在庫の確定、決済の実行、発送手配など)を開始します。
2. 整合性境界の見直しと縮小
「本当に、これらの処理は全てが一つのトランザクションとして結果整合性を保つ必要があるのか?」と問い直し、ビジネスプロセスを分割して整合性の範囲を意図的に狭めてみます。
目的
一つの大きなサーガを、複数の小さな独立したプロセスに分割することで、失敗時の影響範囲を限定し、補償の連鎖を断ち切ります。
これには、ビジネスモデルの見直しが当然必須です。
具体例
①. 巨大なサーガの範囲の状態
旅行予約システムで、「航空券予約」「ホテル予約」「レンタカー予約」を一つの巨大なサーガで管理しているのが、下図のような全体を結果整合性の境界とした場合のケース。
②. サーガを分割し縮小した状態
このビジネスモデルを、「航空券」と「ホテル」だけを予約・決済し、これを一つの整合性境界とする。
予約完了後、ユーザーに対して「オプションとしてレンタカーも予約しますか?」と提案する。
レンタカー予約は、先の予約とは独立した別のプロセスとして扱う。
つまり、図で描くとこういうことです。
赤い方のビジネスプロセスと緑のビジネスプロセスを明確に分割し、
別々のサーガ、別々の結果整合性の境界として考えるのです。
より詳しくは、以下の記事で触れます。
3. 非同期性を前提としたUI/UX設計
結果整合性は時間がかかる、あるいは失敗(補償)する可能性があるという事実を隠さず、
ユーザーにプロセスの状態を正直に伝えるUI/UXを設計します。
目的
ユーザーの期待値を適切に管理し、「確定したと思っていたのに覆された」という体験品質の低下を防ぎます。
具体例
注文ボタンを押した直後に「注文が確定しました!」と表示するのではなく、
「ご注文を受け付けました。現在処理中です。」と表示し、ローディングやステータス表示(例: 支払い処理中→発送準備中)を見せる。
ユーザーには「最終的な確定通知はメールでお知らせします」と伝え、即時確定ではないことを明確にする。
4. タイムアウトとデッドラインの導入
サーガが完了するまでの時間的な上限(タイムアウト) を設けます。
目的
不測の事態でトランザクションが無限に「処理中」の状態でスタックするのを防ぎ、システムを安定させます。
具体例
注文処理サーガ全体のタイムアウトを「15分」と設定します。
15分経っても完了しない場合は、強制的にサーガを失敗とみなし、全ての補償トランザクションを実行して注文をキャンセルします。
同時に関係チームへアラートを通知し、原因調査を促します。