Background:
- we have 2 bounded context: Inventory and Sale
- application context is Point-of-sale system
Scenario:
When a Checkout happen on Sale BC, we would like to decrease quantity in Inventory.
Problem:
We have 2 handlers in this problem that is interested in Checkout
or PurchaseCreated
event:
- The handler from Inventory that will decrease quantity of a Product
- The handler for a Projection that creates denormalized view.
In a synchronous environment like PHP, I can just the right order of the Event listeners.
I would like to know how this is handled in an asynchronous environment?
I would appreciate if the answer is not technology specific because then at least many of us will benefit from the answer.
Why:
The Checkout event only contains (in simplest form):
- Date of transaction
- Product infos (id, name, quantity bought, and current price).
The projection for reporting shows what products are bought and quantity left and total sale.
The order of Event handler is important for the Projection to be accurate. The denormalized view contains data not in the Checkout event which is the "stock quantity".
If the Projection queries the Inventory first, it can subtract the stock quantity to the quantity bought
BUT
If the Inventory handler comes first, it would be inaccurate if stock quantity would be subtracted from quantity bought.
Solution:
Just like VoiceOfUnreason said:
In distributed environments, you are more likely to see an "eventually consistent" approach taken...
The solution in our example based on the quote now is to just query the Inventory for its stock quantity AND listen to ProductTaken event from Inventory BC.
If Inventory handler comes first and then the Projection, then the Stock quantity left is now updated.
If Projection comes first and then the Inventory handler, it will still going to be accurate... eventually. We can listen to ProductTaken and just update accordingly.
The problem in the OP was the Projection tries to subtract quantity bought from Inventory when it should be our source of truth and dont need to do a math operation on them.
1 Answer 1
I would like to know how this is handled in an asynchronous environment?
In an asynchronous environment, you handle this with a sequence barrier. The second action doesn't get to act on the information until the first action has finished. You have a clear happens-before
relation of the two. See, for instance, the work that the LMAX team published about the Disruptor.
In distributed environments, you are more likely to see an "eventually consistent" approach taken, with reports including freshness information for each grain of information. So the projection will show stock levels as of some displayed time, and perhaps some project estimate into the "current" time.
Remember, the information is going to be nanoseconds out of date before anybody gets to see it.
See also Memories, Guesses, and Apologies.
-
Worth reading LMAX technical paper before focus on its implementation.Laiv– Laiv2019年06月14日 09:21:49 +00:00Commented Jun 14, 2019 at 9:21
-
As always, you always give good advises whenever it's tagged ddd/cqrs/es. Do you have any website or blog?captainskippah– captainskippah2019年06月14日 14:58:05 +00:00Commented Jun 14, 2019 at 14:58
-
1cascadefaliure.vocumsineratio.comVoiceOfUnreason– VoiceOfUnreason2019年06月14日 16:19:01 +00:00Commented Jun 14, 2019 at 16:19
Explore related questions
See similar questions with these tags.
Shop -> OrderPlaced -> Payment -> PaymentReceived -> Inventory -> ProductsTaken -> Shipping -> ProductsShipped
. This (roughly) has been an industry standard for 30 years. Notice that there is no branching! Linear system flows are easy to understand/maintain.