Assume I have a dumb repository which stores numbers (for sake of this example). It is dumb because it may only create new record, update specified record and list all the existing records - no other logic included.
But I want to implement a business logic which will allow me to store new records safely, knowing that I will not store a duplicate record. Also I want to update existing records knowing that it will not lead to having duplicates.
Let's start with a creation of new records. The naive approach tells me that I need two steps to add a record:
- (A) read existing records from repository
- (B) check if existing records already contain same record as I need to store
- (C) if existing records are free of duplicates - store record.
Works fine as long as everything runs in a single thread. How about multi-threading?
Another naive approach tells me, that I can introduce the lock around steps A,B,C. I am on a safe side again (let's ignore all the performance considerations).
Now let's consider records update. Steps are similar to creation:
- (A) read all records
- (B) check if duplicates will occur after update
- (C) if check is in our favor - update the record.
Problems with multi-threading again? Just use lock again.
But what about the situation when one thread creates a record 200 while another thread updates record 100 to a value of 200. They both pass their checks on steps (B), both perform steps (C)... ant we end up with a duplicate.
It leads us to a conclusion that the whole design is wrong.
But what is the right design?