Skip to content

Instantly share code, notes, and snippets.

@brendanzab
Last active October 10, 2022 06:36
Show Gist options
  • Star 76 You must be signed in to star a gist
  • Fork 11 You must be signed in to fork a gist
  • Save brendanzab/a6073e73f751a6ca9750f960a92f2afe to your computer and use it in GitHub Desktop.
Save brendanzab/a6073e73f751a6ca9750f960a92f2afe to your computer and use it in GitHub Desktop.
A reading list that I'm collecting while building my Rust ES+CQRS framework: https://github.com/brendanzab/chronicle

Functional, Reactive, and Distributed Systems Bibliography

Books

Event Sourcing and CQRS

Diagram of CQRS+ES

Testing aggregates

Formal foundations

CQRS, DDD and Event Sourcing are informally defined design patterns. It would be nice to see a precise, theoretical foundation for these ideas. This could help find the signal in the noise and reduce confusion for newcomers. Interstingly, akka-persistence is an implementation of event sourcing that seems quite similar to state machine replication. Aggregates in this instance corespond to PersistantActors.

Aggregate design

Example Aggregates

Consistency, Distributed Transactions, and Sagas

CRDTs and Strong Eventual Consistency

Dedalus and Bloom

Split brains

Domain modelling using types and algebras!

Events and business rules map really nicely onto free monads and interpreters.

Designing a CQRS HTTP API

It can be a little hard to match up CQRS with traditional REST routes. There are a number of approaches I have seen mentioned, ranging from embracing RPC-style payloads to trying to translate CRUDful REST calls to commands.

Migrations and Schema Evolution

Table Schemas for Event Store Implementations

Alternatives

Datomic is a very interesting database! It splits the read side from the write side, and uses an append-only log for storing data. Unlike DDD-style event sourcing though, events don't correspond to domain events. Rather they are factual assertions that can be mapped to the more traditional 'CRUD' operations:

CRUD Datomic
Create Assert
Read Read
Update Accumulate
Delete Retract

The nice thing about this is that it allows one to hook into a more powerful and flexible query language than SQL, Datalog, that allows you to do historical querying. There have been questions raised about Datomic's scalability though (citation needed), and the database is tightly coupled to Clojure.

Contrarian Views

Some reality checks:

Implementations in various languages

  • aggregate: a collection of entities that cluster around a single root entity, referred to as the aggregate root.
  • aggregate root: the entity whose uuid corresponds to the uuid that identifies the entire aggregate
  • command: a message corresponding to a request to change the state of an aggregate.
  • entity: some data with an associated uuid.
  • event: a message that records an aggregate's state transition.
  • event log: an append-only record of all the events applied to the domain model.
  • read model: read-optimized caches that are subscribed to updates on the write model. Multiple read models can subscribe to a single read model.
  • uuid: a universally unique identifier.
  • write model: the source of truth of the state of a domain. This is often an event log.
@TimMoore
Copy link

TimMoore commented Mar 2, 2017

I was just made aware of a recently-updated version of Life Beyond Distributed Transactions.

@brendanzab
Copy link
Author

Cheers for that, updated!

@neverfox
Copy link

neverfox commented Jul 15, 2017

I too like the REST API that you mentioned liking the most and I've actually implemented something very similar. However, when I did so, I had to utilize a data store to track things like status. Most outlines of the CQRS/ES architecture just assume you're doing a fire-and-forget on commands that end up flowing through a complex set of asynchronous queues and pipelines before anything makes it into a datastore. Similarly, you cannot rely on the read side to give you a picture of the resource because it could be an older snapshot. You might end up thinking you need to submit the command again. If the commands are idempotent, that wouldn't matter to the state of the system, but it would possibly waste the user's time or confuse them.

So I'm curious how you would actually implement this in CQRS/ES? Would it involve adding a command store to the picture that could then be updated as things happen downstream? Something needs to be able to recall what commands were initiated and whether they're still running, failed, complete etc. Calls to the API have to have somewhere to look to determine the correct response, but this is not addressed in the discussion of the API. What are your thoughts on this?

@peterbean410
Copy link

There s been a new rust es library coming into play, have u tried it out ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment