I am trying to program a simple shopping scenario using event sourcing:
--------------- --------------- ---------------- | OrderService | | ProductService | | PaymentService | ---------------- ------------------ ----------------- |________________|_____________________| | -------------------- | KAFKA | -------------------- | -------------------- | PROCESSOR | -------------------- | -------------------- | DATABASE | -------------------- There are 3 services:
- Order Service: API that receives orders for a product made by a customer
- Product Service: Contains the stock of products
- Payment Service: Makes the payment of the order
Kafka: event store for the different events.
Processor: CQRS processor that generates the view of the current state.
Database: materialized view of the current state.
My main doubt is how deal with a flow like this:
- Order Service is called and creates an event: OrderPlaced
- ProductService checks the availability of a product and based on it creates a ProductReserved or OrderCancelledNoStock event.
- PaymentService processed the payment in case of ProductReserved event, producing a new event: OrderCompleted.
Since it's a pure event sourcing approach ProductService doesn't have a database.
- Is it a good practice to consider the materialized view in the DATABASE as the source of thruth of the system regarding the stock? In my view the only source of thruth should be the events, shouldn't it?
- I see very it likely to find inconsistencies due to the latencies in the DATABASE CQRS process, that's why using the database as the source of thruth is really risky. However having a materialized view seems to be the only way of knowing the current stock of the products and process or not a product order.
Problematic cases that come to my mind:
- Two concurrent OrderPlaced for the same product arrive at ProductService. This calls DATABASE to check if there's product availability (1 product left). Since that's ok both create a ProductReserved event for the same product and PaymenService will process it.
- One OrderPlaced order arrives at ProductService. 1 product left so it publishes ProductReserved. Another order arrives for the same product before the DATABASE is updated by the CQRS process. So it publishes another ProductReserved despite not having enough stock.
What's the recommended way of handling a scenario like this?