2011-09-05 7 views
12

イベントストアからイベントを再生して、特にイベントによって他のイベントが発生する可能性がある場合に、モデルを再構築する際に何が起こるべきかについて悩んでいます。イベントソーシング:他人を誘発して状態を再構築するイベント

たとえば、10回購入したユーザーは優先顧客に昇格し、特定のプロモーションを提供する電子メールを受け取る必要があります。

そのユーザーのモデルを再構築するたびに電子メールを送信したくないのは明らかですが、私たちが10th PurchaseMadeEventを再生すると、これが起こらないようにするにはどうすればよいですか?

答えて

8

イベントの連鎖は非常に扱いにくく、簡単にコントロールできなくなる可能性がありますので、できるだけ避けてください。例えば、私がUserPromotedEvent(おそらくPromoteUserCommandを使って)を上げると書いているシナリオでは、しかし、私は自分のドメインの一部として電子メールの実際の/物理的な送信を考慮しません。代わりに、私はUserPromotedEvent用の追加のハンドラ/非正規化器を作成して、いくつかの追加チェックをメールに送信する必要性を登録することになります。その後、別のプロセスはまだ処理されていない電子メールの情報を収集して送信します。このアプローチは、完全にアクセス可能ではない/スケーラブルな電子メールゲートウェイで発生する可能性のある問題を緩和します。

より一般的には、連鎖するイベントの必要性は、処理のためにSagaを実装することを検討する必要があることを示しています。

2

イベントを再生すると、それらのイベントの生成に伴うドメインロジックがすべて再生されません。通常、ドメインメソッドでイベントを発生させます。そのイベントの発生は、そのドメインオブジェクトの全体的な状態を更新するはずです。例えば

:この例では

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と同じです。イベントハンドラは実行され、イベントを発生させたドメインメソッドは実行されません。

イベントには、ドメインモデルを更新して(更新モデルを読み込みモデルに適用する)必要なものがすべて含まれています。実行されるドメインメソッドによって、イベントを発生させることができます。

こちらがお役に立てば幸いです。より多くの情報を提供する必要があるかどうかを教えてください。

幸運!

6

イベントハンドラからイベントを発生させるべきではありません。代わりにsagasを使用してください。

あなたのケースでは、サガはPurchaseMadeEventを購読し、PromoteCustomer COMMANDを発行し、CustomerPromotedイベントが発生します。再び、CustomerPromotedイベントを購読し、SendEmailToPromotedCustomerコマンドを送信する別のサガがあります。イベントを再生しているときは、CustomerPromotedイベントのサガを購読しないでください。

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

+0

これはかなり古い答えですが、サガは 'PurchaseMadeEvent'を受け取ったときに' PromoteCustomer'コマンドを発行する方法を知っていますか?これは、佐賀には含まれてはならないドメインロジックである、10回の購入を行った顧客に(OPの説明に従って)依存する。おそらく、常に 'TestToPromoteCustomer'を起動して、実際に宣伝を行うために集約をチェックさせますか?これはちょっと不器用だと感じます。どんな洞察もありがとう –

+0

ええ、そうです、佐賀はTestToPromoteCustomerコマンドを送るべきです。保守性のために純度を犠牲にすることは絶対にOKだと思います。 – xelibrion

関連する問題