Search code examples
asynchronouseventsmicroservicesdomain-driven-designevent-driven-design

How to handle time-related events in Event Driven Architecture?


I have a distributed platform which allows customers to make purchases, and the items which are purchased are stored in an inventory:

Sales app -> PurchaseEvent -> Inventory app

The Sales app raises the PurchaseEvent onto a message bus, which is asynchronously consumed by the Inventory app. This all works great.

There's one piece of functionality which makes it possible for two customers to be merged into one. When this happens, a CustomerMergedEvent is raised, and the Inventory app consumes this to update its data (so that all inventory for those two customers is now under one merged customer).

All is smooth when everything works fine. The challenge arrives when there is a performance backlog in PurchaseEvents being consumed. Any purchase consumed by Inventory after the CustomerMergedEvent has been consumed, will not know the customer merge has taken place. We'll also not even be alerted to the fact this has happened.

We could make it so every customer merge results in a new customer, and have the Inventory app alert us if it receives information about a customer which no longer exists. But are there solutions which solve this time-related issue with events on a higher level?


Solution

  • Why can't your inventory service store the fact that Customer A has been merged into Customer B (by a CustomerMergedEvent)? Then all your purchase event processor has to do is check for a previous merge of the customer (potentially recursively: A could be merged into B which could merge into C and so on if there's enough lag) and use the "effective customer" for the purchase.

    An alternative approach (if you can't for some reason record the fact of the merge in the inventory app to inform future processing) is to model a period where a merge is in progress and declare that period over when you're sufficiently sure that no more purchase events for the pre-merge customers will be coming. If the events have a time associated with them, watermarking might be sufficient. Alternatively, if your message bus is partitioned such that all events concerning a given customer are in the same partition (e.g. Kafka/Pulsar/Azure Event Hub), you can write the CustomerMergedEvent denoting that customer A merged into customer B twice: once to customer A's partition and once to customer B's partition (each time intended for their respective customer).