Phillipp

Phillipp

Complex Rating system with Commanded (CQRS/ES)

Hey,

I am actually interested in Event Sourcing for literally years but haven’t used it yet. Last night, I read through the guides in the Commanded documentation and watched the linked 20 minutes talk on Youtube.
The provided examples start to make sense and the overall picture becomes more clear.

Now, I have a project idea in mind for a very long time, which involves a rating system. I knew right from the start that this rating system would be a good opportunity to use Event Sourcing. However, this rating system will be a little bit more complicated in terms of aggregation and business rules.

Let me show you the concept:

The following will be my logical structure:

- parent
--- child
------category_a
------category_b
------category_c
--- category_1
--- category_2
--- category_3
  • parent and child are the actual things I want to be rated.
  • a child has a dynamic list of categories to be rated on, that can change over time, so they have just an identifier, e.g. usability (%RateCategory{subject: "id-of-child", name: "usability", score: 8})
  • a parent also has a dynamic list of categories to be rated, same as child
  • some parents are not ratable, depending on their type
  • the overall rating of a child is a combination of all category ratings for it
  • if a parent is ratable, it has two overall ratings
    • one overall rating as a result of combining its category ratings
    • another rating that combines the overall rating of its children

Here comes the tricky part:

I want to have the concept of rating periods. I am not sure yet how long a period should be, but as soon as one period ends, another starts immediately. This is to track “progress” over time.
In each rating period, a user can rate only once.
Let’s say, there is a rating period every month. In January, a user can rate all categories of a parent and child. Then, in February, the ratings will be “reset” and the user can rate for everything again.

The goal is to track the ratings of a parent and child over time to see if things got better or worse.


So, that was my overall idea for the rating system. Everything else in the system will be done the “usual” way.

What I would like to get from you are some strategies to achieve this. Since I am just starting to get into the ES mindset, I am a bit lost as to how to implement this right now.

Most Liked

slashdotdash

slashdotdash

It sounds like you want to implement your entities’ lifecycle to be within a time period. You can take inspiration from accounting where a ledger is for a given period (e.g. one year) and at the end of each year the ledger is closed. When this occurs the ending balances from the ledger are copied across into a new ledger as the starting balances.

You could design your entities’ event streams to be monthly and at the end of each month have a scheduled command end the rating period and raise a corresponding domain event. This can be used to start the next period:

  1. Whenever a rating period is started, it schedules an EndRatingPeriod command to be executed at the end of the month.
  2. The scheduled EndRatingPeriod command gets automatically dispatched at the end of the month.
  3. This produces a RatingPeriodEnded event.
  4. Which triggers a StartRatingPeriod command to begin the next month’s ratings

Include whatever data you need from the rating period in the period ended event so that it can be included in the command to be copied into the new period. For example you might just copy the average rating per category, not each individual rating.

Commanded scheduler can be used to do the above command scheduling (either using an event handler or process manager).

By splitting the entities into time-delimited event streams (e.g. monthly) you can use read model projections to build aggregated views of the ratings over time. The benefit of this approach is you won’t have unbounded event streams for your entities and limit the number of events within each stream.

slashdotdash

slashdotdash

Yves Reynhout gave a good talk at Explore DDD in 2017 which covers splitting aggregate event streams by time (appointment scheduling product for healthcare).

Where Next?

Popular in Questions Top

stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
New
Kagamiiiii
Student & New to elixir. Nice language. I want to convert a english character, e.g. “a”, which is stored in a variable, to it’s asci...
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
clayschick
I'm trying to create a simple query to select distinct values from a column. If I only use select and distinct I get back a list of uniqu...
New

Other popular topics Top

stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
977 41022 311
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
polypush135
As many of you may have realized by now (sorry for all the posts here) I’ve been working on a db problem where I’m trying to aggregate a ...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
New
mgjohns61585
Could someone help me? I'm making my first elixir program, number guessing game. I can't figure out how to convert the user's guess from ...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
johnnyicon
Hi all, I've just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I'm trying to use Postg...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New

We're in Beta

About us Mission Statement