Avoid database query associated with active session polling#7966
Avoid database query associated with active session polling#7966
Conversation
mitchellhenke
left a comment
There was a problem hiding this comment.
One question about backwards compatibility, but this is great!
76677e8 to
5e529a7
Compare
|
Maybe for a separate pull request, but: I'm wondering if we're polling more aggressively than we should need to. At most, it seems like could ping only just prior to showing the modal (to confirm that the session is in-fact soon to expire) and just as the session is expiring† (to avoid signing out in case the session was extended in another tab). Polling while the modal is active could be nice to automatically dismiss the modal if the session was extended in another tab, but that seems like a nice-to-have and an edge-case, at the cost of at least 3-4 extra network requests per session timing out. † In the case of expiring, we also send two separate requests in quick succession, one to check if the session is active, and then another to trigger the sign-out. Maybe we could do this at the same time? On the other hand, I'm not sure I like the idea of destroying the session in a |
b590fe3 to
f051b01
Compare
The CSRF won't be updated until after the request finishes, even if the modal will be disappeared immediately
…8084) * Remove redundant "remaining" value from timeout API changelog: Internal, Session Timeout, Remove redundant timeout value from session timeout API * Revert session API remaining removal Temporary for first deploy, see https://github.com/18F/identity-idp/pull/8084/files#r1150918192 * Optimistically hide modal on session continue 1. Fixes specs 2. Better user experience, don't have to wait for request to finish before modal is closed, thus making app feel more responsive 3. The previous result handling with `success` would cause a second polling interval to begin * Bring over rest of spec changes from #7966 The CSRF won't be updated until after the request finishes, even if the modal will be disappeared immediately
f051b01 to
567001a
Compare
567001a to
13e95da
Compare
|
I rebased to resolve conflicts and was working to try to get this over the line. I encountered an issue that will need to be investigated further. There seems to be some base validation that's redirecting requests to Steps to reproduce:
Expected: Either (a) the initial session is still live, or (b) if it's not live, the user is redirected |
This does seem to happen on |
What's happening here is we're trying to destroy the session from the JavaScript as a DELETE request after the session is already ended, or at least after the CSRF token we include in the request is no longer valid, so it's the Initially I considered overriding the CSRF exception handling in the controller, but there's probably no way to retain the The only challenge with this would be to find an equivalent behavior to log |
Edit: It may be lost as far as not being available in the session, but it should still be valid, right? |
13e95da to
776f1cf
Compare
|
Marking this ready for review again. I tried to simplify the diff to limit the impact. Separately, I'd like to iteratively work to slice up |
There was a problem hiding this comment.
All the specs call this with string 'form' instead, should we do that for consistency? (I know it gets converted to a string when we parse anyways)
| timeout: :form, | |
| timeout: 'form', |
There was a problem hiding this comment.
Do we still need the html_safe on there? It looks like the only use of this method is for a data- attribute which I expect would be "smarter" about HTML escaping already?
There was a problem hiding this comment.
I'll check this on Monday, this might be one of the things we could remove altogether as a post-deploy cleanup, once we move everything off the current session API endpoints.
I should probably get that follow-on pull request prepped anyways.
There was a problem hiding this comment.
To this and the prior comment, I think I might leave this alone for now. It's still needed, but ties into some bigger problems with the auto-refresh that I'd like to sort out (related Slack discussion). At the very least, it might make sense to just have the JavaScript be responsible for navigating to ?timeout=form, rather than passing a full URL path from the server.
|
Post-deploy clean-up pull request at #8507 |
changelog: Internal, Performance, Avoid database query for session heartbeat polling
session_expired behavior applies to all logged-out screens, so this should continue to exist (for now) in ApplicationController. it also simplifies the diff
To avoid issues for 50/50 deploy and for clients running stale version of JavaScript, to be reverted in follow-on pull request
6369488 to
9b3f3d3
Compare
|
I've been monitoring this in production, and it seems like it has a small improvement over the legacy sessions endpoint in response time (-6% average, -15% median), but notably I observed in the breakdown that a database load is still happening for the user, which... was one of the main motivators for this work in the first place. I'll plan to find some time to troubleshoot why that's happening. It's getting into diminishing returns of value, since the endpoint is already quite fast, and the database load doesn't contribute greatly to the overall response time. It used to be a very highly trafficked endpoint (and still is overall), but we might find more value in other optimizations like preventing some of the intermediate polling in the first place if it's not necessary. |
Follow-up: I traced this back to Curious if we could skip a full user load, I dug into what Devise/Warden store in the session, and it looks like it's the user ID ( |
For posterity: A bit of extra discussion on these points in Slack at https://gsa-tts.slack.com/archives/C0NGESUN5/p1688146380110749 |
🛠 Summary of changes
This
introduces auses the newApi::SessionsControllerto manage active session polling behavior.Proposed benefits:
current_user, instead using internal Warden session valuesSessionsControllerto own dedicated controller with conventionally named methodssession_expires_at,pinged_at)ApplicationControllerand consolidate with session timeout behavior📜 Testing Plan
It's easier to test by setting a very low session timeout in local
config/application.yml: