I am working on design of a distributed system which will process some events. For simplicity lets say, multiple instance of same service will be consuming from same queue, every message will have a id for which the event has generated and it will read the current value of it from the DB and increment it by 1 and update in DB. The service has a SQL with transaction; Pseudo code:
.
.
.
start transaction
state <- read the state from db for the said id
count <- read the count from db for the said id
if no record found
state <- 'QUEUED'
count <- 0
if state == 'QUEUED' and count == 5
state <- 'INPROGRESS'
if state == 'QUEUED' and count < 5
count <- count + 1
update the DB for the said id
commit
.
.
.
Consider, current DB state at 9:59:00:00 am
-------------------
id | count | state
-------------------
0 | 4 | QUEUED
-------------------
There are 2 instances of the service are available and there is one event with id = 1 at 9:59:20:00 am; If the Service(instance-1) takes 3 second to make the updation in DB then at 9:59:23:00 am DB state will be
-------------------
id | count | state
-------------------
0 | 4 | QUEUED
1 | 1 | QUEUED
-------------------
Now there are two events with id = 2 at the same time or very close interval. Say,
Event-1 at 10:00:00:00 am
Event-2 at 10:00:00:50 am
Service instance-1 takes 3 second to process Event-1 and Service instance-2 takes 2 second to process Event-2.
Will this produce any inconsistency, or very time in such scenario it will produce same result (At 10:00:06:00 am for id=2, value=2, state=QUEUED)
-------------------
id | count | state
-------------------
0 | 4 | QUEUED
1 | 1 | QUEUED
2 | 2 | QUEUED
-------------------
To handle this kind of race condition any other good design pattern available, like locking
Thanks in advance for considering this problem statement