Friday, January 11, 2013

How our users exploited concurrency and how we fixed it - Evil Trout's Blog

How our users exploited concurrency and how we fixed it - Evil Trout's Blog: "Fortunately, I soon found an easy solution: let the database handle the concurrency. Much smarter developers than me have put in thousands of hours of work into databases to make sure they hold up under concurrent situations such as these. All I’d have to do is leverage their hard work.

Here’s the solution I came up with:

Player.transaction do

# Update completed attribute to true, but only when it's currently false
row_count = Goal.update_all "completed = true", ["player_id = ? AND completed = false", player.id]

# update the player score only if completed changed in the database
if row_count == 1
player.increment!(:score, goal.score)
end

end
The key to the above solution is that your RDBMS will return a count of how many rows it changes when you execute an UPDATE. Only one request will receive a row count of 1 back. All others will receive 0 and will execute nothing. It just works!

"

'via Blog this'