0

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.

  • The obvious solution here is to not have more than one listener per event. That is, simply chain commands/events such that they occur in whatever order is necessary. I would go so far as to say that your POS design is dangerously flawed. The way an ordering flow should work is as follows: 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. – king-side-slide Jun 14 at 15:37
  • I think this is one of the problem with DDD as it differs from business to business. The POS system that I have in mind here is for markets where there is no long running processes and shipping. OrderPlaced and PaymentReceived is just one event. If card is denied at Counter, there is no purchased created unless paid with cash. – doesnotmatter Jun 14 at 16:50
  • The semantics of how each step in the process is/is not initiated is not relevant. The purpose of the design above is specifically to avoid the problem you are outlining. That is, by having each step of the process initiate the next step, we can ensure the order of processing even in async/eventually consistent systems. Your OP reads like, "If I introduce concurrency into my system, how can I avoid concurrency?". Of course the answer isn't in some technical detail, rather, we must revisit the design itself. – king-side-slide Jun 14 at 17:01
2

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.