イベントソーシング:他の人を引き起こし、状態を再構築するイベント

StackOverflow https://stackoverflow.com/questions/7312540

質問

特にイベントが他のイベントをトリガーする場合に、イベントストアからイベントを再生することでモデルを再構築するときに何が起こるべきかを頭に導くのに苦労しています。

たとえば、10個の購入を行ったユーザーは、優先顧客に宣伝され、特定のプロモーションを提供するメールを受信する必要があります。

そのユーザーのモデルを再構築するたびにメールが送信されたくないことは明らかですが、10日を再生するときにこれが起こるのを防ぐにはどうすればよいですか PurchaseMadeEvent ?

役に立ちましたか?

解決

イベントチェーンは非常にトリッキーで、簡単に制御できなくなる可能性があるため、可能な限り避けます。たとえば、あなたが説明しているシナリオで私は UserPromotedEvent (たぶん使用しています PromoteUserCommand)、しかし、私はドメインの一部として電子メールの実際/物理的な送信を考慮しません。代わりに、追加のハンドラー/デノマリザーを作成します UserPromotedEvent これにより、おそらくいくつかの追加のチェックでメールを送信する必要性が登録されます。その後、別のプロセスは、まだ処理されていない電子メールの情報を収集し、それらを送信します。このアプローチは、完全にアクセスできない/スケーラブルな電子メールゲートウェイで発生する可能性のある問題を軽減します。

より一般的に - イベントの必要性は非常にしばしば、あなたが実装することを検討する必要があることを示しています サガ プロセスのために。

他のヒント

イベントハンドラーからイベントを提起するべきではありません - それをしないでください!使用する必要があります サガ 代わりは。

あなたの場合、SAGAは登録します PurchaseMadeEvent と問題 PromoteCustomer コマンド、それが起こります CustomerPromoted イベント。繰り返しますが、購読する別の物語があります CustomerPromoted イベントと送信 SendEmailToPromotedCustomer 指図。イベントを再生しているとき - サガを購読しないでください CustomerPromoted イベント。

これは、コマンドとイベントの違いに関するものです。それを理解することが重要です。イベントはすでに何が起こったのかを伝え、コマンドは何が起こるかを伝えます。

イベントを再生するとき、これらのイベントを生成することに伴うすべてのドメインロジックを再生することはできません。通常、ドメインメソッドでは、イベントを提起します。そのイベントの調達は、そのドメインオブジェクトの全体的な状態を更新するはずです。

例えば:

public class Purchase {
  private int _id;
  private string _name;
  private string _address;
  private double _amount;

  public Purchase(int id, string name, string address) {
    //do some business rule checking to determine if event is raised

    //perhaps send an email or do some logging
    //etc.
    if (should_i_raise_event) {
      ApplyEvent(new PurchaseMadeEvent() {
        ID = id,
        Name = name,
        Address = address
      });
    } 
  }

  public UpdatePurchase(int id, double amount) {
    //more checking to see if event is to be raised
    if (should_i_raise_event) {
      ApplyEvent(new PurchaseUpdatedEvent() {
        ID = id,
        Amount = amount
      });
    }
  }

  protected void OnPurchaseMade(PurchaseMadeEvent e){
    _id = e.ID;
    _name = e.Name;
    _address = e.Address;
  }

  protected void OnPurchaseUpdated(PurchaseUpdatedEvent e){
    _id = e.ID;
    _amount = e.Amount;
  }
}

この例では、私のイベントが再生されると、 OnPurchaseMade イベントハンドラーは、ドメインオブジェクトコンストラクターではなく、実行されます。と同じです PurchaseUpdatedEvent - イベントハンドラーは実行され、イベントを提起したドメインメソッドではありません。

このイベントには、ドメインモデルを更新するために必要なすべてのものが含まれています(そして、更新を読み取りモデルに適用します)。実行されるドメインメソッドは、イベントを提起できるポイントに到達します。

これが役立つことを願っています。詳細情報を提供する必要がある場合はお知らせください。

幸運を!!

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top