This is a very useful pattern that I see rarely used. When working with systems that pass messages, it can be difficult to later reconstruct a conversation or the sequence of events. It is second nature to us to assign entity IDs1 to messages, but two other IDs will help us to understand the structure of conversations.
One is a correlation ID. This is used to tie the conversation together. When initiating a conversation a correlation ID is created and any reply simply copies the correlation ID as its own.
The other is a causation ID. This is used to record the immediate cause of the message, or which message this is a reply to. When replying, the original message's entity ID is copied as the reply's causation ID.
Messages can be anything: commands, entity events, user input, user data, system events.
I've displayed them in order and used integer IDs instead of UUIDs2 only for readability's sake. To retrieve the conversation we can query our database for all messages with the correlation ID 547, and sort them into a tree using their entity and causation IDs.
| |
This is useful because it allows us to find the causes of downstream issues. In a previous project I worked on, we were consuming data provided by third parties, which would occasionally contain mistakes. If we found that a user of ours had become a multi-billionaire overnight, we could check the causation ID of the responsible event which would direct us to the source file that contained the data.
An advanced form of this pattern allows each message to have several correlation and causation IDs. An event's correlation IDs could point to not just the file that was the source of the data, but also the particular line of the CSV, and the import job. In a risk management service, the warning message can have as its causation IDs all the IDs of the offers that contribute to the risky position.
| |
This necessarily complicates the process of finding immediate and ultimate causes of effects so is only recommended for situations where one is certain it will help.