Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CQRS - When to send confirmation message?

Example: Business rules states that the customer should get a confirmation message (email or similar) when an order has been placed.

Lets say that a NewOrderRegisteredEvent is dispatched from the domain and is picked up by an event listener that sends of the confirmation message. When that is done some other event handler throws an exception or something else goes wrong and the unit of work is rolled back. We've now sent the user a confirmation message for something that was rolled back.

What is the "cqrs" way of solving problems like this where you want to do something after a unit of work has been committed? Another complicating factor is replaying of events. I don't want old confirmation messages to be re-sent whenever I replay recorded events in order to build a new view / projection.

My best theory so far: I've just started to look into the fascinating world of cqrs and was wondering whether this is something that would be implemented as a saga? If a saga is like a state machine where each transition only can take place a single time then I guess that would solve this problem? I just have a hard time visualizing how this will fit together with the command bus and domain events..

like image 775
Kimble Avatar asked Jun 13 '12 13:06

Kimble


1 Answers

  1. An Event should only occur after the transaction has been completed. If anything goes wrong and there's a rollback, then the event didn't occur from an external point of view. Therefore it shouldn't be published at all. Though an OrderRegistrationFailed event could be published if necessary.

  2. You wouldn't want the mail to be sent unless the command has sucessfully been executed.

    First a few reasons why the command handler -- as proposed in another answer -- would be the wrong place: Under some circumstances the command handler wouldn't be able to tell if the command will eventually succeed or not. Having the command handler invoke the mail sending would also put process knowledge inside the command handler, which would break the SRM and too tightly couple business rules with the application layer.

    The mail should be sent after the fact, i.e. from an event handler.

    To prevent this handler from firing during replay, you can just not register it. This works similar to how you test your application. You only register the handlers that you actually need.

    • Production system -> register all event handlers
    • Tests -> register only the tested event handlers
    • Replay -> register only the projection/denormalization handlers

Another - even more loosely coupled, though a bit more complex - possibility would be to have a Saga handle the NewOrderRegisteredEvent and issue a SendMail command to the appropriate bounded context (thanks, Yves Reynhout, for pointing this out in the question's comments).

like image 129
Dennis Traub Avatar answered Oct 30 '22 16:10

Dennis Traub