0

Consider a situation in a CQRS system where a query would change the system's state. For instance, a cache update, a background job, or some other sync or async task. My question is how to handle this situation.

One might say that if you ever faced a condition where a Query has to trigger some changes to your system, then your architecture is flawed you've probably done something wrong, but I think this kind of this situation is something quite common and there is no way to avoid it.

However, the question remains how should our approach be for solving this problem?

Also to give a little more context to work, let's say you have an API endpoint called get-stuff, when calling get-stuff, an api handler issues a query to a query handler (which is probably a synchronous function call. The query handler retrieves the data and returns the results to the caller functions/services. But we have a business requirement to schedule a background job(for some reason...) the first time a user calls get-stuff each day, also we use a caching mechanism in front of the database, whenever new data is fetched by the user, and the cache has to be updated. So as you can see a simple query call needs to change some states and write some data. The question here is how to add these functionalities without damaging our principles and architecture.

I have to add that this is not an exact situation that I personally faced. I only got curious about it and could not find a good answer online. I can not describe an exact scenario but I appreciate a general approach or answer that can be used in different types of situations.

p.s: I only found this question, but the answers do not fulfill my needs and I believed their not practical enough.

Farzin Nasiri
  • 710
  • 1
  • 10
  • 27
  • What is meaning of "sends it back up"? Also it would be good if you provide context more in sequence of step. At which step write is being performed ? – dotnetstep Sep 17 '22 at 06:05
  • @dotnetstep by "sends it back up" I meant, it returns the results to the caller functions/services. To be honest, I asked this question in a general form and this is not a problem I have faced myself, I just got curious about it so a general answer that covers different situations is appreciated. – Farzin Nasiri Sep 17 '22 at 06:40

1 Answers1

1

Two points to make clear:

  • Command vs. Query is based on the desire of something outside the system to change the system's state

  • There's no hard prohibition on a command resulting in a value

So if a request from outside doesn't intrinsically express a desire to update state, it's a query. The process of handling that request may choose to update some state (especially if the state it's updating is non-authoritative, e.g. a cache) for its own purposes, but that implementation detail cannot change the essential query-ness of the request. GetItemsMatchingPredicate doesn't intrinsically update state.

If the request does intrinsically express a desire to change state, it's a command. For atomicity and consistency reasons (CQRS, absent certain assumptions about infrastructure which it might often be advantageous for one not to make, tends to imply something less than absolute strong consistency), that request might want to include some bit of the updated state in an associated response: that does not make it a query.

Levi Ramsey
  • 18,884
  • 1
  • 16
  • 30
  • Thanks, Levi, I've never heard about non-authoritative or authoritative changes in software terminology. Can you explain more? Also does something like triggering a schedual (background job) after a user requested for some date count as a Query? – Farzin Nasiri Sep 18 '22 at 15:43
  • 1
    Typically with CQRS, you have a single write model, which is where authoritative changes to state are made (typically after some validation). You then have arbitrarily many read models which are derived from the write model (if doing microservices, this would include services which implement a different write model but consume from another service in some way: their view of that other write model is not authoritative). – Levi Ramsey Sep 18 '22 at 16:36
  • As for scheduling some background job: as far as the data being requested goes, it's a query; as for the fact that a job is being scheduled, it's a command. So it depends on how the system is decomposed: if the data being requested and the management of background jobs are different systems, then it's a query for the data and a command for background job management. If they're considered the same system (e.g.: the data being requested is itself about what background jobs are scheduled...), then it's a command to that system. – Levi Ramsey Sep 18 '22 at 16:41