2

Domain Driven Design Passing Events to separate Bounded Contexts


A user action in MVC should generate an Event which is passed to a remote (same LAN) Event handler.

What I've tested:

  1. MVC: fire and forget service call (asynchronous) ->
  2. (IIS hosted) WCF which gathers data and populates a message ->
  3. Sent via EasyNetQ/RabbitMQ ServiceBus ->
  4. The event is consumed by a Subscriber (using a DI container initialized from a WCF service endpoint) which handles the event & it's data.

I did some testing to see how it works if the service is called fairly quickly by looping in the MVC side

for (int i = 0; i < 200; i++)
{
        ...
        client.MyServiceMethod(someId, startDate); 
        ...
}

The MessageQueue part is quick, based on the timestamps it is sent to the queue and received by the subscriber within the same second. Looping through the WCF service calls is very slow. It takes many seconds to loop through them. I tried switching from wsHttpBinding to netTcpBinding, and playing with the serviceThrottling in WCF.

WCF isn't compulsory, but it seems like a separate event handling project (on the publisher end) would be beneficial and could be physically located elsewhere from the MVC app (load reduction etc.). Is WCF plausible for a situation like this, or should I try using Windows services or some other self-hosted e.g. console app etc, or potentially using a thread in MVC to generate the event data, or are there better scenarios? What are the best practices in this type of Event handling system? Basically it seems like it would be beneficial to have something generating the Event data since it has to be handled somewhere while not slowing down the UI that the end user is using.

lko
  • 8,161
  • 9
  • 45
  • 62

2 Answers2

2

Instead of trying to roll your own infrastructure like this, I think you would do well to employ a tool like NServiceBus (not free) or MassTransit (free). (I would consider this best practice.)

I can't speak for MassTransit, but my experience with NServiceBus has been very good. You only need to specify which messages go to which queue. You can use several different queueing technologies, but I would recommend starting with the default MSMQ implementation. No WCF configuration nightmares necessary. ;)

All of your message handlers will also be automatically wrapped in a distributed transaction so that if a DB interaction fails, the entire message will be rolled back and you'll be able to try the message again in the future.

Josh Kodroff
  • 27,301
  • 27
  • 95
  • 148
  • Using EasyNetQ as the message queue framework eases the messaging portion as you mention, however it's the event creation (and processing on the receiving end) which is the main issue here in my case. Your points are good but I'm trying to decouple the event/message creation from the e.g. MVC application which is currently in a WCF service. +1 for message queue thoughts/best practices. – lko Apr 07 '14 at 06:47
  • You have a WCF service which wants to publish an event to 1 to many receivers? Then I would recommend you use an off-the-shelf service bus. This is not something you want to try to do yourself as it's quite complicated and has already been solved. – Josh Kodroff Apr 07 '14 at 15:24
2

If I undertood well, your event creation process is "heavy" and you want to avoid to be created in the MVC process. I guess you are sending some information to the WCF service in order to let him prepare the event.

You could think of a 2 consumers scenario avoiding the WCF step:

  1. Your MVC application creates and publish a "light" event with all data required in order to create the "heavy" event (basically with the input data you would pass to WCF)
  2. An EventCreator subscriber consumes this message and prepares the heavy event
  3. Your already existing consumer will then consume the heavy event

EasyNetQ already provides simple functions to publish and consume the message. Most of the tutorials you find online suggest using TopShelf for hosting your consumers in a console application (debug) or windows service (production). EasyNetQ has an example here: EasyNetQ with TopShelf

If you want to "hide" the EasyNetQ dependecy on your MVC project, you could wrap the EasyNetQ IBus to a custom Bus and use an IoC container in order to inject a specific implementation of your bus. The example provided above uses Castle.Windsor as IoC container

Ganto
  • 123
  • 1
  • 6
  • Yes, that is exactly what I meant (the event creation process is heavy). Do you mean that #1 would publish e.g. a normal C# `event` to #2 which then prepares the actual EasyNetQ message in the event handler? http://msdn.microsoft.com/en-us/library/aa645739%28v=vs.71%29.aspx – lko Apr 29 '14 at 06:32
  • 1
    Even the first event would be a `Rabbit` message, but it should be very simple and fast to create so that your MVC controller would return just after sending the event, leaving the havy work to an external subscriber (hosted on a console application or windows service connected to the same bus). So instead of invoking WCF with `client.MyServiceMethod(someId, startDate);` you could use `var message = new MyMessage { Id = someId, Date = startDate }; bus.Publish(message);` – Ganto Apr 29 '14 at 09:33