Broadcasting & SoC in Phoenix

Upcoming Phoenix 1.3 offers new folder structure which pushes us to separate our domain logic and web interface.

Often we need to broadcast domain events to Phoenix channels to make live update functionality. However simply calling MyApp.Web.SomeChannel.broadcast! right from some domain module violates the above principle because it makes domain logic depend on the web interface.

A possible solution is PubSub pattern. We create an event bus process where domain modules publish events to. Then in a channel which is a part of web interface we subscribe to this bus and when a new event arrives a callback function is being invoked.

One way to implement PubSub bus is Registry module introduced in Elixir 1.4. I wrapped the example from the documentaion into a separate module in my project like this:

And added it to the app’s supervision tree:

Now in any domain module I can publish a message like MyApp.DomainPubSub.publish("foo", {:some_event, foo}) where foo is some domain entity.

Here I subscribed a channel to this kind of events:

When a client joins to the channel the process responsible for communicating with him subscribes to foo.

handle_info is the callback that is being called when the process receives a message. There we can call our broadcast without violating the separation of concerns principle which makes our code more loosely coupled.

When the client parts the channel we unsubscribe him from future events (though the socket is still alive). If the process gets crashed then Registry is smart enough to unregister the process automatically.

Happy refactoring!