Building Conduit - Applying CQRS/ES to an Elixir and Phoenix web app (self-published)


#1

I’m working on a CQRS/ES and Phoenix book for those interested in building an event driven application using Elixir.


The full source code for the application, Conduit, is available on GitHub.


How would you recommend learning Phoenix today?
Books on the design of web application architecture
Your ideas for Elixir book authors and content creators
#2

Have you thought about contacting Pragprog or Manning Ben? Professional editing and direction is priceless Imo :slight_smile:

Also, how does your book fit in with Martin Fowler’s EDA thoughts?


#3

I opted for the self publishing route as I considered the subject matter too niche for a technical publisher, and wanted the freedom to write at my own pace.

The book takes a step-by-step approach to building a REST API using CQRS and event sourcing for the core domain model.

I’m also considering writing a chapter on “live queries” whereby Phoenix channels are used to push read model updates down to the client, in response to published domain events. I’ve already built a working prototype in another, closed source, web app that can be extracted.


#4

Tangentially related, I’ve been very curious about how GraphQL would line up with CQRS because from a prima facie perspective there seem to be some important similarities. GraphQL also breaks up operations into reads (queries), commands (mutations) and you get live reads (subscriptions) in there as well.


#5

I haven’t used GraphQL, but it looks well suited for use as the read model in a CQRS application.

You would define a schema/types for data to be queried. GraphQL mutations would be executed in response to published domain events to update data. Standard GraphQL queries can be used to display the data.

Typically a read model in a CQRS application will be fully denormalised to eliminate joins. A separate, read optimised, data model is created to support each particular query. In SQL, queries are ideally just SELECT * FROM table WHERE ....

I’d be interested to look into GraphQL’s subscriptions for pushing query updates down to the client. In the past I’ve used read model projections (i.e. CQRS event handlers) to publish notifications, using Phoenix pub/sub, when the data changes. You’d get this behaviour for free if you used GraphQL mutations.


#6

Here’s an example read model projection, using Commanded Ecto projections and Ecto.Multi, from the Conduit sample application from the book.

defmodule Conduit.Accounts.Projectors.User do
  use Commanded.Projections.Ecto, name: "accounts_users"

  alias Conduit.Accounts.Events.UserRegistered
  alias Conduit.Accounts.User

  project %UserRegistered{} = registered do
    Ecto.Multi.insert(multi, :user, %User{
      uuid: registered.uuid,
      username: registered.username,
      email: registered.email,
      hashed_password: registered.hashed_password,
      bio: nil,
      image: nil,
    })
  end
end

An example query:

defmodule Conduit.Accounts.Queries.UserByEmail do
  import Ecto.Query

  alias Conduit.Accounts.User

  def new(email) do
    from u in User,
    where: u.email == ^email
  end
end

You could apply the same pattern using GraphQL in place of Ecto.


#7

this book is completed 30%, are you planning to complete it in near future?


#8

Yes, it will be finished. It’s a stuggle to find the time in addition to consultancy, releasing the next versions of Commanded and EventStore libraries, writing documentation and providing support.


#9

Nice to see there is a conference about your commanded library :slight_smile:


#10

commanded - also got notable mention in this talk