Marinus Geuze
Marinus Geuze

Reputation: 111

Seeking Patterns to Address Concurrent Update Challenges in a Domain-Driven Design Context

Our development team is currently exploring effective patterns to handle situations where concurrent updates might lead to data inconsistencies. We adhere to Domain-Driven Design (DDD) principles, incorporating invariants checks within our codebase.

To illustrate the challenge, consider the following examples:

Example 1: Unique Username Requirement:

Problem: Two users concurrently attempt to register with the same username. Consequence: Both queries to validate username uniqueness return true, leading to the addition of two users with the same username.

Example 2: Batch Job Execution:

Problem: Two users start a batch job simultaneously, violating the constraint of allowing only one job execution instance. Consequence: Both job executions are started concurrently, contrary to the intended single execution.

Example 3: Budget Limit in Shopping Basket:

Problem: A user surpasses the budget limit by adding two items concurrently, exploiting a race condition. Consequence: Both additions are allowed, exceeding the budget limit.

After research, we've identified several potential patterns to address these issues:

1. Database Unique Constraint:

Pros: Resolves example 1. Cons: May not be a comprehensive solution for examples 2 and 3.

2. DDD Techniques for Aggregates:

Pros: Introduces a new transaction boundary. Cons: Not a direct solution for example 1; effectiveness varies for examples 2 and 3.

3. Cluster-Aware Command Handler:

Pros: Handles commands in sequence, potentially resolving all three scenarios. Cons: Adds complexity to the system.

4. Lock Table:

Pros: Can resolve example 2. Cons: Adds complexity; may not address all scenarios.

5. Database Locks (Pessimistic Locking):

Pros: Can be a solution for example 2. Cons: Implementation complexity.

6. No Action (Tradeoff Decision):

Pros: Weighs the cost of implementation against the likelihood and impact of concurrency issues. Cons: Accepts a certain level of risk.

7. Addition to variant 6: Quality Reports for Duplicate Data Detection:

Pros: Offers a monitoring approach. Cons: Reactive rather than preventative.

Our queries for the community:

  1. Other Patterns: Are there additional patterns to address concurrent update challenges?

  2. Pattern Catalogs: Are there well-known pattern catalogs that explain these patterns along with their pros and cons?

  3. Code Examples: Are there code examples of these patterns specifically tailored for Java, JPA, and/or Spring Data?

We appreciate your insights and assistance in navigating this challenge.

Thank you!

Upvotes: 1

Views: 144

Answers (1)

pnschofield
pnschofield

Reputation: 899

Each of the problems presented is unique and each requires its own solution. Here are my suggestions:

Example 1: I would use a unique constraint in the database. I think this is more-or-less the consensus view of DDD experts I have heard discuss the problem.

Example 2: I might have a saga for jobs. There would be an instance of the saga for each type of job. When the user wants to start the job, he sends a command to start the job, the appropriate saga instance handles it by updating its status to "Started" and publishing an event which actually starts the work. Optimistic concurrency on the saga, along with the outbox pattern would prevent the job from being started twice.

Example 3 Adding an item to the cart would go through the aggregate root for the cart. Use optimistic concurrency on the cart.

Upvotes: 1

Related Questions