14

問題:

2 人の従業員 (A と B) が同時にオフラインになり、顧客 #123、たとえばバージョン #20 を編集している間、オフラインで変更を続けています...

シナリオ:

1 - 2 人の従業員が顧客番号 123 を編集し、1 つ以上の同一の属性を変更します。

2 - 2 人の従業員が顧客番号 123 を編集しますが、同じ変更は行いません (2 人は触れずに互いに交差します)。

...その後、両方がオンラインに戻り、最初に従業員 A が追加され、それによって顧客がバージョン #21 に変更され、次に従業員 B が引き続きバージョン #20 に変更されます

質問:

シナリオ 1 で保持するのは誰の変更ですか?

シナリオ 2 でマージを行うにはどうすればよいですか?

環境:

1 - CQRS + イベント ソーシング スタイル システム

2 - イベント ソーシング データベースをキューとして使用する

3 - 読み取りモデルの結果整合性

4 - RESTful API

視覚的に傾いているための図。 これは MS ダイアグラムのマッシュアップであり、いくつかの点が変更されています

EDIT-1:これまでの回答に基づく説明:

きめの細かいマージを実行するには、たとえば、フォームのフィールドごとに 1 つのコマンドが必要ですか?

ここに画像の説明を入力

上記の、ChangeName、ChangeSupplier、ChangeDescription などのきめ細かいコマンドは、それぞれ独自のタイムスタンプを持ち、イベント A と B の両方が ChangedName? を更新した場合に自動マージを可能にします。

編集-2: 特定のイベント ストアの使用に基づくフォローアップ:

イベントストリームの永続化のために @GetEventStore を利用するようです。

次のように、楽観的同時実行性を利用します。

  • ストリーム内のイベントごとに、ストリーム バージョンが 1 ずつインクリメントされます

  • 書き込みでは、ライターの ES-ExpectedVersion ヘッダーを使用して、期待されるバージョンを指定できます

    • -1 は、ストリームが存在しないことを指定します

    • 0 以上はストリーム バージョンを指定します

    • ストリームがそのバージョンにない場合、書き込みは失敗します。期待される新しいバージョン番号で再試行するか、動作を再処理して、必要に応じて問題ないと判断します。

  • ES-Expected Version が指定されていない場合、楽観的同時実行制御は無効になります

  • このコンテキストでは、オプティミスティック コンカレンシーはメッセージ ID だけでなく、イベント # にも基づいています。

4

4 に答える 4

5

あなたの設計図を正しく理解していれば、時々接続するユーザーはコマンド、つまり変更要求をキューに入れ、ユーザーが再接続すると、キューに入れられたコマンドが一緒に送信されます。データベース権限は 1 つだけです (コマンド ハンドラーがクエリを実行して、集合体の最新バージョンをロードします)。ビュー モデルのみがクライアントに同期されます。

このセットアップでは、シナリオ 2は設計によって自明に自動マージされます。コマンドを賢く選択する場合は、以下を参照してください: コマンドをきめ細かくする: 可能なすべての変更に対して、1 つのコマンドを選択します。次に、クライアントの再接続時に、コマンドは任意の順序で処理されますが、分離フィールドにのみ影響するため、問題はありません。

  1. お客様は v20 です。
  2. A はオフラインで、v20 の古いモデルに対して変更を編集します。
  3. B はオフラインで、v20 の古いモデルに対して変更を編集します。
  4. A がオンラインになり、バッチがキューに入れられChangeNameたコマンドを送信し、v20 の Customer がロードされ、v21 として永続化されます。
  5. B がオンラインになり、バッチがキューに入れられChangeAddressたコマンドを送信し、v21 の Customer がロードされ、v22 として永続化されます。
  6. データベースには、予想どおり、正しい名前と住所を持つユーザーが含まれています。

シナリオ 1では、この設定で、両方の従業員が他の従業員の変更を上書きします。

  1. お客様は v20 です。
  2. A はオフラインで、v20 の古いモデルに対して変更を編集します。
  3. B はオフラインで、v20 の古いモデルに対して変更を編集します。
  4. A がオンラインになり、バッチがキューに入れられChangeNameたコマンドを「John Doe」に送信し、v20 の Customer がロードされ、「John Doe」という名前の v21 として永続化されます。
  5. B がオンラインになり、バッチがキューに入れられChangeNameたコマンドを「Joan d'Arc」に送信します。v21 の Customer (「John Doe」という名前) がロードされ、v22 (「Joan d'Arc」という名前) として永続化されます。
  6. データベースには「Joan d'Arc」という名前のユーザーが含まれています。

B が A より先にオンラインになる場合は、その逆です。

  1. お客様は v20 です。
  2. A はオフラインで、v20 の古いモデルに対して変更を編集します。
  3. B はオフラインで、v20 の古いモデルに対して変更を編集します。
  4. B がオンラインになり、バッチがキューに入れられChangeNameたコマンドを「Joan d'Arc」に送信します。v20 の Customer がロードされ、v21 (「Joan d'Arc」という名前) として永続化されます。
  5. A がオンラインになり、バッチがキューに入れられChangeNameたコマンドを「John Doe」に送信します。v21 の Customer がロードされ、「John Doe」という名前で v22 として永続化されます。
  6. データベースには「John Doe」という名前のユーザーが含まれています。

競合検出を有効にするには、次の 2 つの方法があります。

  1. コマンドの作成日 (つまり、従業員の変更時刻)Customer. これにより、シナリオ 2 の自動マージ機能が無効になりますが、同時編集に対する完全な競合検出が提供されます。
  2. コマンドの作成日 (つまり、従業員が変更された時刻) が、変更しようとしている個々のフィールドの最終変更日よりも後になっているかどうかを確認してください。これにより、シナリオ 2 の自動マージはそのまま残りますが、シナリオ 1 では自動競合検出が提供されます。Customer

どちらも、イベント ソーシングを使用して簡単に実装できます (イベント ストリーム内の個々のイベントのタイムスタンプはおそらくわかっているため)。

「シナリオ 1 で保持するのは誰の変更ですか?」という質問については、-- これは、ビジネス ドメインとその要件によって異なります。

EDIT-1: 説明の質問に答えるには:

はい、個別に変更できる各フィールド (またはフィールドのグループ) ごとに 1 つのコマンドが必要です。

モックアップについて: 表示されているのは、典型的な「CRUD」UI、つまり複数のフォーム フィールドと、たとえば 1 つの「保存」ボタンです。CQRS は通常、自然に「タスク ベース」の UI と組み合わされます。たとえば、Statusフィールドが表示され (読み取り専用)、ユーザーがステータスを変更したい場合は、「ステータスの変更」などの 1 回のクリックで済みます。 " ボタン。ダイアログ/新しいウィンドウまたはその他の UI 要素が開き、ステータスを変更できます (Web ベースのシステムでは、インプレース編集も一般的です)。各タスクがすべてのフィールドの小さなサブセットのみに影響する「タスク ベース」の UI を実行している場合、ChangeName、ChangeSupplier などのきめ細かいコマンドが自然に適合します。

于 2014-08-11T12:50:18.430 に答える
4

いくつかのソリューションの一般的な概要を次に示します。

シナリオ 1

誰か、できれば人間が決める必要があります。ユーザーに尋ねるか、競合があることを示す必要があります。

Dropbox は、後のファイルを選択し、同じディレクトリに file.conflict ファイルを保持して、ユーザーが削除または使用できるようにすることで、これを解決します。

シナリオ 2

元のデータを保持し、実際に変更されたフィールドを確認します。次に、つま先を踏むことなく、従業員 1 の変更を適用し、次に従業員 2 の変更を適用できます。

シナリオ 3 (変更が異なるタイミングでオンラインになる場合のみ)

2 番目のユーザーに、オフライン中に変更があったことを知らせます。シナリオ 2 を試み、2 番目のユーザーに新しい結果を表示します (これによりユーザーの入力が変更される可能性があるため)。次に、変更を保存するか、最初に変更するか、破棄するかを尋ねます。

于 2014-08-10T00:33:40.557 に答える
0

この場合、これらの複雑な操作を実行するために、CEP エンジン (Complex Event Process Engine) を利用した Item に対して「集約ルート」の概念を使用できるかもしれません。

于 2016-10-25T08:43:22.763 に答える