0

I am new at Domain Driven and CQRS and confused a bit about event handler mechanism.

Domian events are firing an event occured. For example an Account created.

public class Account: AggregateRoot{        
      public Account(Guid id)
      {
          Apply(new AccountCreatedEvent { AggregateRootId = id });
      }
}
public class AccountCratedEvent: DomainEvent{
}

I think this is an inner event mechanism for Domain. So I can not send an email to new account owner. Because new account has not saved to database yet. So should I create a new event handler to populate after database savings?

barteloma
  • 6,403
  • 14
  • 79
  • 173
  • possible duplicate of [Persistence and Domain Events with persistence ignorant objects](http://stackoverflow.com/questions/22194403/persistence-and-domain-events-with-persistence-ignorant-objects) – Martijn van den Broek Mar 23 '15 at 11:02

2 Answers2

0

Yes this is a common question. Depending on the exact nature of your domain, you may want to opt for 1 of 2 possible locations to send emails from:

The easiest place to put it is as an event handler. This assumes a few things:

  • It doesn't matter if all the event handlers complete successfully
  • The event and or read model has all the info required to send the message. Importantly, the read model is not reliant on the completion of the updates (eventual consistency issue).
  • Your message sending infrastructure is simple

If any of those things are a problem then you need to use a Process Manager. This is a device that can listen to events and issue commands. In this case, on successful completion of all the events, issue a command to send an email.

I've written a more detailed blog post covering this topic. You can read it here: How to Send Emails the Right Way in a CQRS System

Codescribler
  • 2,235
  • 18
  • 22
  • Your blog comments are closed, and I think you're doing it wrong ;-) Why do you think that events and commands are at the same level?, but depending of some magic keywords it will either trigger an event or call a command. – Janus007 May 29 '15 at 17:08
  • Not sure I understand your point. Within a CQRS ES setup, a command represents an action. An event is something that represents a state change. I'm not sure what I understand the 'same level' bit. Can you elaborate. – Codescribler May 29 '15 at 19:56
  • Hi CodeScribler I've read your blog post again and it seems that I jumped over the ProcessManager, my apologies for that.. I agree with your logic, certainly the ProcessManager could be written more elegant without breaking open-closed but that is another story. cont. – Janus007 Jun 01 '15 at 21:02
  • It seems here and there that a lot developers are confused around when an email should be sent and when a command should be executed. As usual the problem is conceptual and the belief is often that an email should be executed inside an event handler, i.e. AccountCreatedEvent. But in reality and as you perfectly cover in your blog post a command is always triggered by an event and that fact together with the rule that no logic should exists in event-triggers makes it easy to grasp imho. – Janus007 Jun 01 '15 at 21:04
0

Apply() an event does not equal to sending it out immediately although your domain model will handle the events right away like:

public class Account: AggregateRoot{        
    public Account(Guid id)
    {
        Apply(new AccountCreatedEvent { AggregateRootId = id });
    }
    public void handle(AccountCreatedEvent event) 
    {
        this.id = event.AggregateRootId
        this.status = "New"
    }
}

The implementation of Apply() usually just handle the event on the aggregate it self and cache the events raised. Other objects, usually Repository is responsible for getting the cached events and emitting them.

Yugang Zhou
  • 7,123
  • 6
  • 32
  • 60
  • is Account created event an event of domain itself? I can send email after saving database. – barteloma Apr 01 '15 at 05:56
  • No, AccountCreatedEvent is not an "internal" event by your definition. It is an event that can be published. But the publishing does not happen immediately when the Apply() is executed, instead, The implementation of Apply() usually caches the events in a unit of work. The event should be published after the unit or work is committed. – Yugang Zhou Apr 01 '15 at 06:45