Let’s say I have 2 types of messages. MessageA and MessageB.
- MessageA creates an entry in DB.
- MessageB updates an entry in DB.
Most cases, MessageA is sent with long-interval with MessageB. However, there are some cases where both message are sent seconds apart from each other. It might happen that MessageA is still creating DB entry, but MessageB tries to update non-existent.
How to handle this kind of scenario? I understand there are 2 options:
- Retry / Dead Letter Queue – message is sent back to queue and retried again until it reaches max delivery count and moved to Dead Letter Queue
- Defer – message is deferred until it is explicitly read
Which is the best practice?
- 1 seems to be good, but still can be the case it reaches max retries,
but DB entry not yet created. - 2 seems to be good, but need to do additional coding and
infrastructure (Redis and Background Task) for periodically checking
deferred messages
2
Answers
There is a third option for dealing with these kinds of race condition (which is not always possible, depending on the nature of the messages):
A practical example: Say we have a school database with Year Group and Student entities. To create a new student, a message is sent with all the student details. To create a new Year Group, a message is sent with a Year Group name and list of StudentIds that should belong to that year group.
If the Year Group message is received before all the students are received, you can create a placeholder student entity with just the student ID (and perhaps a flag to identify that it is a placeholder).
When the Student message is received, it can simply add or update the existing record, and fill in all the student details.
If you had to choose one of the two options you listed, it depends:
For scenarios such as this, where message order is required, Service Bus provides a feature to ensure messages are processed in the order they were originally sent – Message Sessions.