Zveratko
Zveratko

Reputation: 2810

How searches with criteria should be implemented in Event sourcing with CQRS

Let's say I need to query for all entities which comply with given criteria. My biggest confusion is about where the data should be taken from. I guess we have two option, either query event store itself or ask some other projection storage solution(have no idea - maybe some DB or what). It maybe depend on the amount of events processed. How will the implementation look like?

  1. asking directly the event store we will query all entities and then filter them in application?
  2. using DB we will just query the underlying table, which is taylored for specific criteria search

What about performance?.

In event store the best one can do is probably to create some snapshots, not sure anyway how to list complex so called "aggregates". In DB we will have nearly the same count of rows as events, which will end up in extensive DB optimalization. Not to mention that this DB can be dropped anytime and filled again which I completely cannot imagine. Do I get the things right or am I completely of the track?

Upvotes: 2

Views: 3350

Answers (2)

Brad Irby
Brad Irby

Reputation: 2542

You don’t quite have the proper mental view of CQRS yet. The C of CQRS is for commands which only update data. They instantiate an entity in memory using events in the event store, make the proper changes, then store those changes back to the event store. This side is not meant for adhoc queries. Think of the Command side as data you are only allowed to access via the primary key.

The read side is where you would query for all entities with a particular attribute. The read side is built in a DB (not an event store) by special code that listens to the event store and adds/updates rows in the read side DB to keep it up to date. Note that the read side DB is not third normal form – data is often duplicated and there are very few foreign keys.

So, while it is technically possible to query most event stores for specific attributes, but it’s clumsy since that’s not what they were designed for. To get collections of objects you query the read side.

Walking through a typical example

  1. User arrives on your site and clicks a button to see a list of blue T-shirts. You query the read side for all Inventory entities with Type="TShirt" and Color="Blue", and return this list to the user screen with a counter of how many are in stock.
  2. The user clicks on a t-shirt so you query the read side for details on the shirt and a picture. Show the user that screen using that info.
  3. The user adds the t-shirt to the cart. You execute the AddItemToCart command which creates a CartCreated event, then an ItemAddedToCart event, then an InventoryDecremented event.
  4. The read side is subscribing to the event source and sees these events, so it updates its tables appropriately.
  5. A second user comes in that also wants a blue t-shirt, but she sees that inventory is now 0 since the previous person got the last one. All that info comes from the read side DB only, not the event source (command side).

If you keep the two sides separate in your mind, many questions of how to implement something just fade away.

Upvotes: 3

Nachiappan Kumarappan
Nachiappan Kumarappan

Reputation: 291

Event Sourcing: is a way of developing an application in which all information is persisted as events. For more info refer here

Example: If we are developing a banking software, the events that we store will be something like below

  • User1, transacted : 100, reference : "xyz", Date : 11th October 2018
  • User1, transacted : -100, reference : "xyza", Date : 18th October 2018
  • and so on...

Now if the User1 wants to debit his/her account, then we pull all the events from his/her stream and replay to get the balance. And if he/she has sufficient balance then we debit his/her account by adding one debit event.

This process takes a bit of time, and it is generally done only when there is a need to write in to the system (Writes are less common than reads in most systems). Though this takes a bit of time, it gives us the benefit of audit-ablity, security and running analytics.

The difficulties in a event sourced system are for querying. If we need to get a list of users who deposited more than 10000 units in a quarter, then its going to be difficult and time consuming as we need to replay the every users stream. To solve this we can use CQRS.

CQRS: is a pattern of developing software where the writes are done by one application and reads are done by another application. More information available here. The write application and read application could communicate with each other (may be by messaging). The read application could maintain it's own database and store the information in the shape that is comfortable for querying. So when the read application gets a message, it converts the message that is suitable for it's own db schema and store it.

The read application will eventually (probably in couple of seconds) be consistent with the write application. The read application will be able to handle queries quickly very quickly as its database schema is designed for it.

Now answering your question:

  • There is a bit of time taken for updating data in the write appliation. The write application replays all the events (or the events after snapshot) before any update. As long as the aggregates are small and we employ proper snapshotting techniques the performance is not bad.
  • The read model has it's own database, the schema is designed to suit querying. Many a times we don't worry about redundant data in the read database. This is designed to make queries fast.
  • We could decide to throw the read applications (models) data and rebuild it in another shape to suite new queries as the source of truth is the events stored in the write application (model).

Upvotes: 0

Related Questions