Thanks for your reply! I "feel" there is similarity, resonance... but still I cannot really grasp it. Can you try to make your description "less meta"? 😉 The examples in my post are about what to record inside a software to track state changes. Your examples seem to be about the development process of software and you're calling it "genealogical development". I am a little confused (but I like the allusion to quantum mechanics).
Hi Ralph, this was a very inspiring post. One question came to my mind when I've tried to model it. What is your idea to keep the related event references around so you can correctly pass them with newly triggered events? Do you think keeping them in a session context? Or propagate into read models so for example when I press the button on a screen, I thread it into the command and later to event? Thx.
Keep event ids around where it's convenient for you. They can be part of a context model or read model.
Example: The user enters the names of the players of a TTT game to start a game. A GameStarted{players: "Peter, Mary", gameStaredId: "123"} event is created.
To return the gameStartedId from the command I find legitimate, even though commands don't have a result. Nevertheless, though, they should signal success/failure. Part of that signal can be the id of the event.
When later issuing the command for making a move, the id can be passed in to select the right context: MakeMove(fieldIndex:2, id: "123"). It will become the scope reference for the event recording the move, eg tokenPlaced{fieldIndex: 2, scopes: {gameStartedId: "123"}}
In this case the UI remembered the id. But you can keep it in a session context or a read model.
Yes, this goes in line with my way of thinking. I was looking for some kind of semi-universal principle that allows me to not hardcode a specific logic either to UI or a session that assigns specific historical event ID(s) to the one I am about to create. But that seems to be dependent on the situation. I'll read through the article you send. Skimming it seems it should give some reassurances to me. Thanks.
If you need to put a new event into a scope you have to find the scope root. Either you know its event id, or you search for it eg by event type and some payload property. Example: you want to link a move to a game? Query the event stream for { eventtype: "gameStarted", payload: { playernames: ["Peter", "Mary"] }} (if player names happen to be unique among all games).
Where the player names (or other reference information) come from is up to you. Maybe the user entered it for the new event, or... you have remembered it from a previous request (command, query).
Also, I'm trying to think how to migrate data from my 10-year old CRUD application (many dozens of entities and RDBMS tables) into an AQ system. Maybe simple "entity migrated" events to start with.
I do appreciate your ideas. Previously, ES and CQRS and bounded contexts and aggregates and what not were hard for my team to grasp. This approach is very straight-forward. The necessary projections for queries and reports seem obvious.
This was a great read. Inspiring and hit close to home. I felt like I needed to respond immediately because it resonates so deeply with the course we're on. https://thetimethatremains.substack.com/p/events-in-superposition
Thanks for your reply! I "feel" there is similarity, resonance... but still I cannot really grasp it. Can you try to make your description "less meta"? 😉 The examples in my post are about what to record inside a software to track state changes. Your examples seem to be about the development process of software and you're calling it "genealogical development". I am a little confused (but I like the allusion to quantum mechanics).
Hi Ralph, this was a very inspiring post. One question came to my mind when I've tried to model it. What is your idea to keep the related event references around so you can correctly pass them with newly triggered events? Do you think keeping them in a session context? Or propagate into read models so for example when I press the button on a screen, I thread it into the command and later to event? Thx.
Glad you liked the article, Ladislav!
Keep event ids around where it's convenient for you. They can be part of a context model or read model.
Example: The user enters the names of the players of a TTT game to start a game. A GameStarted{players: "Peter, Mary", gameStaredId: "123"} event is created.
To return the gameStartedId from the command I find legitimate, even though commands don't have a result. Nevertheless, though, they should signal success/failure. Part of that signal can be the id of the event.
When later issuing the command for making a move, the id can be passed in to select the right context: MakeMove(fieldIndex:2, id: "123"). It will become the scope reference for the event recording the move, eg tokenPlaced{fieldIndex: 2, scopes: {gameStartedId: "123"}}
In this case the UI remembered the id. But you can keep it in a session context or a read model.
See this article for scopes: https://ralfwestphal.substack.com/p/scoping-events
Yes, this goes in line with my way of thinking. I was looking for some kind of semi-universal principle that allows me to not hardcode a specific logic either to UI or a session that assigns specific historical event ID(s) to the one I am about to create. But that seems to be dependent on the situation. I'll read through the article you send. Skimming it seems it should give some reassurances to me. Thanks.
If you need to put a new event into a scope you have to find the scope root. Either you know its event id, or you search for it eg by event type and some payload property. Example: you want to link a move to a game? Query the event stream for { eventtype: "gameStarted", payload: { playernames: ["Peter", "Mary"] }} (if player names happen to be unique among all games).
Where the player names (or other reference information) come from is up to you. Maybe the user entered it for the new event, or... you have remembered it from a previous request (command, query).
Ralf, these are very interesting articles and much appreciated.
Do you know of a reference architecture, or an example system built along these lines? Or should we all be trying to write one?
Also, do you feel like a purpose-built graph database would be a more effective or performant event store, compared to a traditional RDBMS?
Thanks,
Dave
Glad you like the article!
There are no examples yet for Story Recording. But Rico and I are working on them. Subscribe to this substack and you'll be informed... 😉
If a graph database or some purpose built database or an RDBMS is the best choice we'll see. It probably depends on several aspects.
For now I am concerned with a convincing concept. If the concept holds then efficient implementations will be found. It happened with RDBMS, too.
Also, I'm trying to think how to migrate data from my 10-year old CRUD application (many dozens of entities and RDBMS tables) into an AQ system. Maybe simple "entity migrated" events to start with.
I do appreciate your ideas. Previously, ES and CQRS and bounded contexts and aggregates and what not were hard for my team to grasp. This approach is very straight-forward. The necessary projections for queries and reports seem obvious.
This is not a small project. Please send me a DM on LinkedIn and we'll find a way to talk about this.