开发者

messaging from the model level to controller level for ajax purposes

开发者 https://www.devze.com 2023-04-11 06:48 出处:网络
I have a page called /examples/1/duplicate on there is an ajax form which kicks off /examples/1/run_duplicate

I have a page called /examples/1/duplicate on there is an ajax form which kicks off /examples/1/run_duplicate

开发者_Python百科

the controller method for run_duplicate runs Example.duplicate(session) I pass in the session, which I understand is a holy no-no.

the duplicate model code is roughly:

def duplicate(session)
   session[:duplicate] = 0
   duplicate_foobars
   session[:duplicate] = 1
   duplicate_snafus
   session[:duplicate] = 2
   duplicate_widgets 
   session[:duplicate] = 3
end

I have another controller method on the duplicate page which is doing a long poll: /examples/1/check_dupe_status The purpose was to get the updated status from session[:duplicate], tweak a progress report, and report it back to the user via ajax so they could see the progress of Example.duplicate() .

sessions did not update the way I hoped. I can see the code run, but the sessions don't update, so /examples/1/check_dupe_status never knows that anything has kicked off.

Given that I did this wrong from the start, what is the correct way to notify a user about the state of Example.duplicate() ?


Sounds like you've got two separate requests, with one writing to the session and one trying to read from the session concurrently. Is that correct? Stop reading if it's not.

This can not work because the "session" is just a cookie - a header on the HTTP response that's downloaded to your browser as a cookie, then re-uploaded on the next request, then re-downloaded on the next response, ad nosium. In your code, here is the order of operations:

  1. /examples/1/run_duplicate writes "0" to what is essentially a Ruby Hash, representing your session cookie

  2. /examples/1/check_dupe_status reads the values from the session cookie that was just sent from your browser with this request. It probably didn't have anything at all in :duplicate, so it will appear as blank.

  3. /examples/1/run_duplicate writes "1" to the Ruby session Hash

  4. /examples/1/check_dupe_status reads, again, the session cookie which that request sent - nothing has changed

  5. /examples/1/run_duplicate writes "2" to the Ruby session Hash

  6. /examples/1/check_dupe_status reads from the session cookie it originally sent - no change

  7. /examples/1/run_duplicate writes "3" to the Ruby session Hash and the request finishes, sending the session back as a cookie with a value of 3 at :duplicate.

  8. /examples/1/check_dupe_status is still sitting there like a dufus, reading the blank session cookie it originally sent

At some point, /examples/1/check_dupe_status may timeout, and it may return with the session cookie. But guess what? Since :duplicate was never set in that session cookie, it will overwrite the one in your browser, and :duplicate will be blank in the next request you send.

Hopefully I expressed that clearly. Basically you're hitting a race condition in your cookies, and that's very difficult to overcome if you're sending concurrent requests from the same browser.

The best way to handle this would be to write your duplicate 0,1,2, etc. values to some database table. Your long-polling request could then just read out of the database. A little less efficient perhaps, but of course it has the advantage that it could work.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号