I want to design a system which is similar with stackoverflow review feature. That is to say:
There are n
tasks, which should assign to users (users count is unknown). At one time, one task should assign to at most one user, different users should not be assigned same task.
For example, n = 8, if one user enters the system default assign him 3 tasks.
- At 17:00, Tom enters the system and get tasks 1, 2, 3.
- At 17:01, Jim enters the system and get tasks 4, 5, 6.
- At 17:02, Jerry enters the system and get tasks 7, 8.
- At 17:03, Bob enters the system and get no task.
- At 17:05, Tom completed task 1, 2, and leave the system.
- At 17:06, Bob enters the system again and get task 3.
Suppose I use Database to store tasks info.
My solution is that when tasks 1, 2, 3 are assigned to Tom, delete the 3 records from DB and store them to memory. Then others will not get the 3 records. When Tom leaves the system, insert his completed tasks and uncompleted tasks to DB again (with task status "completed" or "uncompleted").
While the disadvantage is that store records to memory is not 100% safe, if the system crashed may cause data missing issue.
Could somebody know how stackoverflow designs review feature? Or share other solutions? I'm wondering whether SELECT ... FOR UPDATE
is good in this use case.
What you need to implement is a FIFO stack or simple queue. In Oracle the best thing (unless you want to implement an actual queue with AQ) for such a thing is
SELECT ... FOR UPDATE
with theSKIP LOCKED
clause.SKIP LOCKED
allows us to easily operate a stack with multiple users.Here's a simple interface:
This is a bare-bones implementation:
Updating the status when the users pops the stack creates a lock. Because of the
SKIP LOCKED
clause, the next user won't see that task. This is a lot cleaner than deleting and re-inserting records.Here's some data:
Let's pop! Here's Session one:
Meanwhile in Session two:
Back in Session one:
The main drawback of this approach is that it requires users to maintain stateful sessions while they work on the task. It that's not the case then you need an API in which
get_next_task()
is a discrete transaction, and forget about locking.Incidentally, it's probably better to let users grab a task rather than assign them through a logon trigger (or whatever you have in mind by "Tom enters the system and get tasks 1, 2, 3."). Pulling tasks is how the SO Review queue works.
Also, just assign one task at a time. That way you can get efficient distribution of work. You want to avoid the situation where Tom has three tasks on his plate, one of which he isn't going to complete, and Bob has nothing to do. That is, unless you're Bob.