简体   繁体   中英

Race conditions over shared resources in domain driven design

Problem description

I'm trying to implement application according to Domain Driven Design,

For this question, let's assume that we have a simple domain that is responsible for managing reservations of some events.

Each event has a limit of participants, so the system shouldn't allow making too many reservations.

The procedure of making a reservation may like below:

  1. Load event aggregate from the repository.
  2. Check if the event is full, if yes then stop.
  3. Make a reservation for an event
  4. Save the event in the repository.

My issue is how to resolve the below race condition:

Many users may want to make reservations at the same time, so we may end up with two parallel executions that may load event aggregate at the same moment, both see that there is still a free slot for that event and make a reservation which may lead to making too many reservations.

This is a classic concurrency issue, but I'm looking for an approach that works in DDD world.

What ideas I tried:

Use database mechanism of concurrency control

The procedure could be wrapped in a database transaction, and use to detect that two writes were happening over the same event. Then one transaction will fail, and we can retry the procedure for this user.

I think it doesn't fit DDD as the domain layer would be aware of database transactions, which as far as I understand should be avoided, all database-related activities should have a place in the infrastructure layer (repositories).

Application layer concurrency control

Some concurrency control may be implemented on the application layer, for example locking mechanisms so that only one execution of procedure may happen for the given event at the time.

That sounds better to me as we don't base on database implementation of handling logic, and our logic model remains clear.

What is bothering me is that we may have few machines that are processing such procedures, then we need to have some common locking mechanism for such cases.

Perhaps there is also a different way of solving this scenario? I'm open to any suggestions.

I think it doesn't fit DDD as the domain layer would be aware of database transactions, which as far as I understand should be avoided, all database-related activities should have a place in the infrastructure layer (repositories).

I'm not sure why you assume that pessimistic locking enforced at the DB level requires domain pollution? Transactions are generally managed in the application layer (possibly through a Unit of Work ) so you could easily apply a transaction isolation level that serializes all transactions.

You may also use optimistic concurrency (with retry) either with a version or full data compare which most ORMs supports out of the box.

You may have to introduce a version property in the model (slight infrastructure pollution) to support version-based optimistic concurrency, but this leakage can be hidden in a Layer Supertype .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM