Источник событий: события, которые запускают других и восстанавливают состояние - PullRequest
12 голосов
/ 06 сентября 2011

Я изо всех сил пытаюсь разобраться, что должно произойти при перестроении модели путем воспроизведения событий из EventStore, в частности, когда события могут вызвать другие события.

Например, пользователь, у которого естьСделанные 10 покупок должны быть продвинуты до предпочтительного клиента и получать электронное письмо с предложением определенных акций.

Мы явно не хотим, чтобы электронное письмо отправлялось каждый раз, когда мы перестраиваем модель для этого пользователя, но какостановить это, когда мы переиграем наш 10 PurchaseMadeEvent?

Ответы [ 3 ]

10 голосов
/ 06 сентября 2011

Цепочка событий может быть очень сложной и легко выходит из-под контроля, поэтому я бы избегал этого как можно больше.Например, в описываемом вами сценарии я бы поднял UserPromotedEvent (возможно, даже используя PromoteUserCommand), однако я бы не стал рассматривать фактическую / физическую отправку электронного письма как часть моего домена.Вместо этого я бы создал дополнительный обработчик / денормализатор для UserPromotedEvent, который бы регистрировал необходимость отправки электронной почты с некоторыми дополнительными проверками, вполне возможно.После этого другой процесс будет собирать информацию о еще не обработанных письмах и отправлять их.Этот подход позволил бы смягчить проблемы, которые могут возникнуть с не полностью доступным / масштабируемым почтовым шлюзом.

В более общем плане - необходимость цепочки событий очень часто указывает на то, что вам следует рассмотреть возможность реализации Saga дляпроцесс.

6 голосов
/ 06 сентября 2011

Вы не должны вызывать событие из обработчика событий - просто не делайте этого!Вы должны использовать sagas вместо этого.

В вашем случае сага подписывается на PurchaseMadeEvent и выдает PromoteCustomer COMMAND, что вызывает событие CustomerPromoted.Опять же, есть другая сага, которая подписывается на событие CustomerPromoted и отправляет команду SendEmailToPromotedCustomer.Когда вы воспроизводите события - просто не подписывайтесь на сагу для события CustomerPromoted.

Это все о разнице между командой и событием.Это важно понимать.События рассказывают о том, что уже произошло, команды сообщают о том, что произойдет.

3 голосов
/ 06 сентября 2011

Когда вы воспроизводите события, вы не воспроизводите всю логику домена, которая сопровождала генерацию этих событий. Обычно в методе вашего домена вы вызываете событие; повышение этого события затем должно обновить общее состояние этого объекта домена.

Например:

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 - будет выполняться обработчик события, а не метод домена, который вызвал событие.

Событие содержит все, что нужно для обновления модели домена (и применения обновлений к модели чтения). Методы домена, которые выполняются, приводят вас к тому, что событие может быть вызвано.

Надеюсь, это поможет. Дайте мне знать, если мне нужно будет предоставить больше информации.

Удачи !!

...