I will simplify my problem:
My LightsState API can receive 2 type of inputs: lightOn {lightId: ##}
and lightOff {lightId: ##}
. (AMQP input but irelevant here)
These inputs translate well into 2 Commands: TurnLightOnCmd
and TurnLightOffCmd
.
These commands will create 2 Events: LightTurnedOnEvent
and LightTurnedOffEvent
.
These events will be applied to the Light Aggregate
and the persisted projection will be the state of the light
.
All good until here.
But because there is no input: create light
, i can not make a CreateLightCmd
from that. I can only invoke a CreateLightCmd
when I receive a lightOn
input with a NEW lightId
to create a Light Aggregate
and then also apply TurnLightOnCmd
on it.
I am not sure how to handle this and also follow good CQRS practices.
Is it ok to call the Query side from Command side to check if light exists by id
and then invoke CreateLightCmd
first if needed?
Or should I make a db query from within the Command side and keep the Command and Query sides decoupled?
Or are there any other solutions to this?
Thanks
Not really - that introduces race conditions, the consequences of which may not make you happy.
Review: DDD+CQRS+ES is very similar architecturally to DDD alone. The basic notion was that we persist information into our storage appliance (aka "the database"). The model runs in a process that loads the current state from the database, uses the command to compute a new state, and then stores that new state in the database.
The same pattern holds when we are doing event sourcing - we read the history from the database we use for writes, compute new events, and append those events to the history.
But: creation patterns are weird.
When we try to query for the history of an identifier that we haven't seen before, then we are going to get a null, or a
None
, or a history with no events in it, or something like that.The surprise is: that's fine.
For your use case, you wouldn't necessarily want a
CreateLightCmd
-- instead, you want to produce a newLightCreatedEvent
when you get one of the other commands that should implicitly create the light.In pseudo code: