I was looking at an auditing pattern to save history of my entity and I came across Event Sourcing Pattern. It is an interesting pattern and most of it makes sense to me but I had one question on how to implement a certain use case scenario?
Use Case:
From my understanding of event store. It should only contain the actions that were applied on the entity.So the event always has the updated transaction amounts(payment and adjustment) and status.
Database:
Invoice:
| id | balance | payment | adjustment | status |
|-------|---------|---------|------------|----------|
| 12345 | 10 | 70 | 20 | Paid |
Event Store:
| event_id | invoice_id | Event | Payload |
|----------|------------|------------------|---------|
| 1 | 12345 | Invoice_InReview | JSON |
| 2 | 12345 | Invoice_Billed | JSON |
| 3 | 12345 | Invoice_Paid | JSON |
| 4 | 12345 | Invoice_Reversed | JSON |
| 5 | 12345 | Invoice_Paid | JSON |
JSON contains info about changes to payment,adjustment and status
So here are my questions
from what I understand the balances will be fine but the invoice status will be incorrect.
Please advise me on how to best handle this on event sourcing pattern.
I get how balances can be reversed but I do not see how we can accomplish the same effect for status
So the first thing to do would be to check with your domain experts to understand if the ubiquitous language has the concept of the status of an invoice between the reversal and the repayment.
Based on what I see here, I would expect a reversal by itself to put the status on billed again. We thought it was paid, but that entry is a mistake, so we would restore the object to its previous state.
If that were correct, then we would have a status of Billed
there.
But it might not be -- this isn't an undo, it's a behavior within your domain. It might be that this moves the domain to a previously undiscovered part of the state machine.
how will I handle if api calls(commands) come out of order for the above events.
There are two different questions that may be hidden there - I will summarize each.
If you are worried about downstream consumers reacting to events, it is important to design your consumers such that -- if they need to know the entire history, then they read from the history. A consumer that reacts to the changes in history will read an ordered history from the event store, rather than reacting to messages that appear on message transport. In other words, the published event acts like a notification, telling the consumer to refresh its copy of the history.
If you are worried about the fact that you get the "wrong" history if commands appear out of order, then you need to review and integrate Udi Dahan's essay Race Conditions Don't Exist
A microsecond difference in timing shouldn’t make a difference to core business behaviors.