Long story short: Ruby on Rails session handling does have some concurrency problems. Especially with AJAX requests this is a very potential scenario:
- Request 1 loads user session
- Request 2 loads user session
- Request 1 stores something to the session
- Request 2 stores something to the session
- Request 1 writes its session data to the database
- Request 2 writes its session data to the database
Now, of course whatever request 1 wrote there is pretty much lost. These bugs are hard to find, and in my case the site had been in production use for 18 months before this really became a problem.
I soon found out that Frederick Cheung had already written a plugin called Smart Session Store to handle these race conditions by locking the session row when needed. However, it didn’t work with the latest PostgreSQL drivers.
I’ve fixed this to work with combinations of the pg/postgers driver and Rails 2.2/2.3 in my smartsessionstore fork. The tests are also now actually testing something. I’ve sent a pull request, so everyone should be able to enjoy it soon.
It’s really a good practice to somehow handle session concurrency even before it’s a problem, because these kinds of bugs tend to appear when you least expect it.
We can test this by adding two actions to our controller. They should both write something to the session, and the other one should sleep a while to make sure that its changes are likely to be lost.