Command accros multiple aggregates with CQRS and ES

342 Views Asked by At

I'm having an odd case while thinking about a solution for my problem.

A quick recap: I'm using an event store with CQRS, and i have 2 aggregates called 'Group' and 'User'.

Basically a User defines some characteristics like his region, age, and a couple of interests.

He then can choose to 'match' with a Group that is in the same region, around the same age and same interests.

Now here's the case: the 'matchmaking' part should happen completely on the backend, it can be a long running process, but for the client it's just 1 call to the endpoint and the end result should be him matching with a group.

So for this case, I have to query the groups which have the same region, the same age slice, the interests don't really matter in my query. I know have a list of groups, and the match maker is going to give each group a rating based on the common interests between the group and the user. The group with the best rating will be joined.

So again, using CQRS and ES, and my problem is that this case seems a mix between queries and a command, and mixing queries into a match command seems to go against the purpose of CQRS.

Querying multiple groups and filtering them against my write side, the event store, also is a bad idea as the aggregates have to be rebuilt and loaded in memory before being able to filter them out.

So I:m kind of stuck here, something is telling me that a long running process / saga could be an answer to my problem, but I don't see how I would still not break the mix of query and commands in my saga, as a saga is basically a chain of commands/events.

How do I tackle this specific case ? No real code is needed, a conceptual solution to get me going is perfect.

1

There are 1 best solutions below

0
On BEST ANSWER

Hi this is actually a case where CQRS can shine.

Creating a dedicated matching model seems to be ideal for this case to allow answering what might be a rather non-trivial query in other forms.

So,

  1. create a dedicated (possibly ephemeral, possibly checkpointed/persisted) query model as derived store.
  2. Upon request run a query to get the top matches.
  3. based on the results of the query send a command to update the event store with the new links.

The query model will not need to manage commands and could be updated on a push basis from the event store. This will keep it rather simple to build and keep up to date and further can be optimized to only have the data needed for for this particular query.

An in-memory graph might do well.

-Chris

p.s.

On the command side: the commands here would each only update a single aggregate instance.

Further using the write ahead pattern would allow for not needing any sort of process manager or "saga."

e.g.

For each new membership 1 command to add the new membership to the user stream, then 1 command to the group to add the new member information. Then a simple audit process can scan for incomplete membership assignments both on start up/recovery and as a periodic data quality check.

-Chris