CQRS / ES with Rails

Mirosław Pragłowski / @mpraglowski

LOB apps

What are the main concerns?

LOB apps

What is important to Business?

Features

Quick changes

Maintainability

Cost

Performance

Pains?

CQRS & ES, it really is a ES & CQRS.

You can use CQRS without ES, but with ES you must use CQRS.

by Greg Young

Event sourcing

...but first

Eventual consistency

Consistency of data is a state which is eventually attained

...what leads us to CAP theorem

CAP theorem

  • Consistency all nodes see the same data at the same time
  • Availability a guarantee that every request receives a response about whether it succeeded or failed
  • Partition tolerance the system continues to operate despite arbitrary message loss or failure of part of the system

CAP theorem

...a distributed system cannot satisfy all three of these guarantees at the same time...

Eric Brewer

CAP theorem

Centralized system

we don't have network partitions (P)

... so it is CA system

Distributed system

we have network partitions (P)

... so it can be only CP or AP system

AP samples?

Amazon ;)

Tickets buying system

CP samples?

ATM application ;)

... but let's back to

Event sourcing

Storing a state

Storing events

Events

Something that has had already happened

Represents state change

Should be named in past tense

... and in business language (Ubiquitous Language)

They never change!

... unless you have a time machine

... or you play Orwell and rewrite history

Storing events (revisited)

Pros of ES

  • Avoiding impedance mismatch (ORM)
  • Append only store - we never loose any data
  • Audit log for free
  • Complete rebuild, we could discard state and rebuild it by re-running events
  • Events can be replayed if there is a need to re-process old data
  • Easy to do temporal queries
  • Easy to implement different read models
  • Performance improvement (easier to scale)

Cons of ES

  • You could not change anything in database
  • ... but hey, that's I would count as pros :)
  • It takes a while to change your mindset
  • Need of separate models for reporting
  • ... but hey, that's not really a bad thing!
  • Lack of tooling

Typical RoR app

Typical RoR app

Complex RoR app

Complex RoR app

Here will be dragons!

Separating reads from writes

CQRS

Did you mean CARS?

CQRS

Command and Query Responsibility Segregation

term coined by Greg Young (@gregyoung)

also Udi Dahan (@udidahan) involved

based on CQS devised by Bertrand Meyer

Bertrand defines CQS as: every method should either be a command that performs an action, or a query that returns data to the caller, but not both. In other words, asking a question should not change the answer.

Commands

Named in business language (Ubiquitous Language)

Express user's intention

Simple validations (regardless of context)

Rejection by exception or fault event

Can be asynchronous

a.k.a Form Object

Command Handlers

Handle commands :)

Entry point to your domain

Handle all plumbing

Cross cutting concerns as Chain Of Responsibility

Triggered by users, external systems or sagas (process managers)

a.k.a Service Object (some of them)

Events

Something that has had already happened

Represents state change

Should be named in past tense

... and in business language (Ubiquitous Language)

They never change!

... unless you have a time machine

... or you play Orwell and rewrite history

Aggregates

A place where (almost) all yours app logic should be

Set of objects holding consistent/valid state

Protecting invariants

... more in DDD books :)

Aggregates with CQRS/ES

State rebuild based on events

Source of new events

Do not expose state

Read Models

The model as your app needs it

Denormalized!

Tailor-made!

Recreatable!

Could be anything: relational DB, NoSQL store, graph database

... static HTML file ;)

a.k.a Query Objects (in half baked CQRS implementation with shared database)

CQRS app

CQRS app

Pros of CQRS

  • Performance
  • ... we could have database optimized for reads
  • ... and we could scale reading independently of writing
  • Simplicity & ease of changes in read side
  • Decluttering domain (moving reads to read model)
  • Easier to test

Cons of CQRS

  • Still pretty new and not familiar to devs
  • ... and requires mindset change
  • Requires more infrastructure
  • Must remember about eventual consistency
  • ... but hey, we deal with this every day

?

Resources

blogs:

Resources

books, docs & articles:

Resources

samples:

Resources

communities:

Available at

https://talks.praglowski.com/cqrs-es/

Sample code

https://github.com/mpraglowski/cqrses-sample/