My Rails session is getting reset when I have concurrent requests
I think I might be misunderstanding something about Rails sessions, so please bear with me, I might not be phrasing my question the best way.
I'm working on an iPhone app with a Ruby on Rails backend. I have a web view which by default goes to the index action of one controller (and uses sessions), and in the background a bunch of API calls going to a different controller (and which don't need to use sessions).
The problem is, the sessions set by my web view seem to be overwitten by the API calls. My staging server is pretty slow, so there's lots of time for the requests to overlap each other - what I see in the logs is basically this:
Request A (first controller) starts. Session开发者_StackOverflow社区 is empty.
Request B (second controller) starts. Session is empty.
Request A finishes. Request A has done authentication, and stored the user ID in the session. Session contains user ID.
Request B finishes. Session is empty.
Request C starts. Session is empty - not what I want.
Now, the strange thing is that request B should NOT be writing anything to the session.
I do have before and after filters which READ from the session - things like:
user = User.find_by_id(session[:id])
or
logger.debug session.inspect
and if I remove all of those, then everything works as expected - session contents get set by request A, and they're still there when request C starts.
So. I think I'm missing something about how sessions work. Why would reading from the session overwrite it? Should I be accessing it some other way? Am I completely on the wrong track and the problem is elsewhere?
Thank you for any insights!
This is the result of a race condition caused by how rails handles session. See http://www.paulbutcher.com/2007/05/race-conditions-in-rails-sessions-and-how-to-fix-them/
It seems like you can't have concurrent requests modifying session reliable. The solution is to use a different method of storing session (e.g. active_record or redis) or you could eliminate the concurrent requests.
Your sessions are maybe cookie based. If that's the case then each of request is starting with the same cookie(session). The cookie holds the session content. Try switching the storage to be on the server. But I in your case with the authentication I think it would be much better to not do this async.
Request A (first controller) starts. Session is empty.
Request B (second controller) starts. Session is empty.
Request A finishes. Request A has done authentication, and stored the user ID in the session. Session contains user ID
.....AND returning the session content in a cookie.
Request B finishes. Session is empty.
THIS one is setting blank session.
Request C starts. Session is empty - not what I want.
Thats because B has set reset the session
It's possible this is because you are storing the user id as ":id" in the session object. :id may be a reserved key in the object. Try using a different name such as session[:user_id].
Good luck!
精彩评论