I'm building a platform that has an entity named
content. There's a clear boundary around what defines
content except that it can have relationships with other
Up until now, there's been no need to know anything about that related
content until read-time, at which point my projections have taken care of the read requests.
I now have a requirement that certain commands should fail if the
content has a related
content with a certain state.
I'm considering using my projections at the time of the command to do a quick sanity check to validate the command and then use the
saga pattern to do the real confirmation (at which point I can reverse the previous event if we find that it's not actually valid). I'm having a hard time figuring out how to avoid race conditions for the hard validation down the line.
Imagine we have
- In order for any Content to be published, all related content must also be in a published state.
- Content 1 has a relationship with Content 2 and Content 3 (this is a one-way relationship)
- All content is currently unpublished.
- content-2, publishContent
- This succeeds because Content 2 does not own the relationship to any other content.
- content-3, publishContent
- This succeeds because Content 3 does not own the relationship to any other content.
- content-1, publishContent
- This has to check Content-2 and Content-3 to confirm that they are in a published state.
How can I confirm that nothing has become unpublished between checking the state of Content 1 and the state of Content 2? Or between checking those states and persisting the event? I was thinking maybe I could let it go through if the initial checks pass and then do another check on any
contentUnpublished events that make it through to revert the
contentPublished that probably should have failed, but there's no good way to determine the inverse of those relationships through my source of truth (the event store).
How can I implement this validation in a way that stays true to Event Sourcing and CQRS patterns?