Renato Gama
Renato Gama

Reputation: 16599

How to trigger an action only after receiving two or more events in an event driven architecture?

I have started implementing microservices in an Event-Driven Architecture. Therefore some of my services are publishing events and listening to some other events. It is very straightforward to implement a listener when an action depends on one single event, for example;

ORDER SERVICE 
  1. Publishes `ORDER_INTENT_EVENT` then
  2. Listens for `CREDIT_AVAILABLE_EVENT` then
  3. Finishes the `Order`

CREDIT SERVICE
  1. Listens for `ORDER_INTENT_EVENT` then
  2. Verifies if the client has credit then locks the amount and
  3. Publishes `CREDIT_AVAILABLE_EVENT`

The problem arises when OrderService has to wait for more than one event, for example;

ORDER SERVICE 
  1. Publishes `ORDER_INTENT_EVENT` then
  2. Listens for `CREDIT_AVAILABLE_EVENT` 
             and `INVENTORY_AVAILABLE_EVENT` then <--- Problem here

  3. Finishes the `Order`

CREDIT SERVICE
  1. Listens for `ORDER_INTENT_EVENT` then
  2. Verifies if the client has credit then locks the amount and
  3. Publishes `CREDIT_AVAILABLE_EVENT`

INVENTORY SERVICE
  1. Listens for `ORDER_INTENT_EVENT` then
  2. Verifies if inventory has items then locks the items and
  3. Publishes `INVENTORY_AVAILABLE_EVENT`

The thing is; I am pooling both queues CREDIT_AVAILABLE_QUEUE and INVENTORY_AVAILABLE_QUEUE, and both events has to be present so I can finish an order. How can I coordinate so that OrderService sees both events as only one?

I can implement it at the application level, for example; if one event arises I save it to the database and check if there is the other corresponding event to same order, if so I proceed with finishing the order, if not I do nothing then when the other event arrives I will have both of them so I am able to finish the order. The problem with this approach is that there is a minimal chance of receiving both events at the same time generating race conditions.

What is the suggested pattern for this kind of scenario?

PS.: I found this similar question but one answer suggests .net related tools and the other points to a third party service. I am interested in a pattern/code solution.

Upvotes: 3

Views: 1338

Answers (1)

Rob Conklin
Rob Conklin

Reputation: 9473

Any time you have multiple input sources to a particular piece of state, you have the potential for a race condition. This is why we have locks. You MUST use a lock of some sort to handle the race condition.

This may be implemented at the database layer, or using a locking library, or a shared piece of memory (please use a locking library unless you have way more understanding of memory / CPU architecture than this posting implies).

Most languages implement some form of mutex locking to allow this problem to be solved. If you are using multiple processes / machines / etc, you will need some form of external mutex locking (often implemented by your database provider). If you lack this, there are distributed lock systems that also can be used.

Upvotes: 0

Related Questions