The Bus

We’ve been working in the area just outside of our Domain Model in terms of building Command Handlers and coordinating activities on the Domain in these Command Handlers. How do Commands make it to our Command Handlers? What if multiple parties are interested in an Aggregate’s state change Event? How does the Read Model find out about Events that are happening in our Write Model?

The answer is the Bus…

“Typically, the bus is a singleton. It receives requests to execute commands and event notifications. The bus doesn’t actually do any concrete work. It just selects a registered component to process the command or handle the event. The bus holds a list of known business processes triggered by commands and events, or advanced by additional commands.” - Dino Esposito

There are two main components to a Bus:

In Greg Young’s SimpleCQRS solution, he implemented a FakeBus that is backed by an in-memory Dictionary<Type, List<Action<Message>>> for a Message Router:

public class FakeBus : ICommandSender, IEventPublisher {
    private readonly Dictionary<Type, List<Action<Message>>> _routes = new Dictionary<Type, List<Action<Message>>>();

    ...

}

The Message Router simply maps Command/Event types to their respective Command/Event Handlers via a Registration that would be done in our Composition Root, e.g. in the Global.asax.cs in Greg’s project:

protected void Application_Start() {

	// instantiate Bus, other stuff and dependencies (or wire up IoC container)

    bus.RegisterHandler<CheckInItemsToInventory>(commands.Handle);

    ...

}

The public void RegisterHandler<T>(Action<T> handler) where T : Message method takes an ICommandHandler<TCommand>.Handle(TCommand message) method and stores it in a list ofhandlersfor a specifictypeof(T)` message.

public void RegisterHandler<T>(Action<T> handler) where T : Message {
    List<Action<Message>> handlers;

    if (!_routes.TryGetValue(typeof(T), out handlers)) {
        handlers = new List<Action<Message>>();
        _routes.Add(typeof(T), handlers);
    }

    handlers.Add((x => handler((T) x)));
}

So when we call:

protected void Application_Start() {

	// instantiate Bus, other stuff and dependencies (or wire up IoC container)

	bus.RegisterHandler<StartCreatingRoastScheduleCommand>(
	    new StartCreatingRoastScheduleCommandHandler(repo).Handle);

	...

}

We have told the Bus to send StartCreatingRoastScheduleCommand to StartCreatingRoastScheduleCommandHandler.Handle method.

For a pretty neat Message Router library written in F# and compatible with C# and VB.NET, check out Quicken Loans’ MessageRouter.

Also, keep in mind that I plan to talk more about the more production-level Bus solutions out there. They include projects like:

Next up, let’s talk about publishing using Events in our architecture to achieve our goals.


continue reading…

previous…


I will be releasing most of this content only to subscribers. Make sure you sign up by clicking the big red button!


Related Posts:

Tweet
comments powered by Disqus