Skip to content
This repository has been archived by the owner on Feb 8, 2018. It is now read-only.

Throttle set_session_expires. #2041

Closed
wants to merge 4 commits into from
Closed

Throttle set_session_expires. #2041

wants to merge 4 commits into from

Conversation

zwn
Copy link
Contributor

@zwn zwn commented Feb 16, 2014

set_session_expires used to update the field session_expires in the participants
table on each http hit.

From #1878 (comment)

return
c.run( "UPDATE participants SET session_expires=%s "
"WHERE id=%s AND is_suspicious IS NOT true"
, (expires, self.id,)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've never quite understood with self.db.get_cursor() as c:. I just looked up what with does, and that's actually pretty cool. So, going further:

  • What does self.db.get_cursor() do to this code? What would happen without it? Does the FOR UPDATE lock expire at the end of the with block?
  • I'm confused how this fixes the problem of multiple threads trying to update the same data. It seems like now those threads might each still attempt the SQL UPDATE at the same time. It's just that now all but one would fail, because the first thread locked the row.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lock expires with the end of the transaction. When a thread encounters a locked row, it blocks until the lock is released. Therefore only the first thread does the update, the next ones get the updated value and skip the update. Now thinking about it, it can be made simpler.

Please do not merge for now.

@zwn
Copy link
Contributor Author

zwn commented Mar 2, 2014

@seanlinsley How about now?

@zwn zwn mentioned this pull request Mar 3, 2014
if done is None:
return
add_event(c, 'participant',
dict(action='set', id=self.id, values=dict(session_expires=unicode(expires))))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there really a need to record this event? Seems like that's going to bloat the database without adding value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The final goal here is to be able to recreate the whole db the events table. So all changes should be logged here. See #1549 (comment) for the general plan.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would we ever want to recreate session_expires? Why are we storing this in the database in the first place?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like a signed / encrypted cookie would be a much better approach.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 If only you had asked me 17 days ago 😀. I have been trying to find with 🔦 where it is used for some time now. It seems.... surprise surprise... that nowhere ‼️. Thank you!

Just dumping the column session_expires and all code related to it would not change a bit about the site behavior. The participant object is just created from session_token gittip/security/authentication.py#L49. Grepping for expires brings up only code related to writing it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

35% of our participants table has an expired session (session_token is not null and session_expires < now()).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(P.S. 1.3% have a non-expired session.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just killed old sessions with this:

update participants set session_token=null where session_expires < now();

Looks like we don't reset session_expires in Participant.end_session, which is also a bug. But we should probably clean up such things in a separate PR, eh?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zwn @seanlinsley So what's the next step here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. update this PR so we don't store an event
  2. update the code so we don't respect expired sessions
  3. (optional, after this PR) instead of storing in the database, sign the cookie with something like tokenlib, ref: move caching out of memory #715

@seanlinsley
Copy link
Contributor

In an effort to get through our outstanding PRs, I'm going to take this on.

@seanlinsley
Copy link
Contributor

Rebased on master (7731357 -> 5641344)

@zwn
Copy link
Contributor Author

zwn commented Mar 19, 2014

@seanlinsley Thanks. The original point of this PR was to "fix" writing to session_expires on each and every hit for signed in users.

@clone1018
Copy link
Contributor

@seanlinsley How can I help get this one done? Do we need a hackaton?

@clone1018
Copy link
Contributor

Just found #2041 (comment) thanks to @seanlinsley . I'll check it out tonight.

zwn added 4 commits April 26, 2014 13:05
set_session_expires used to update the field `session_expires` in the participants
table on each http hit.
When we do hit the database, it is going to be hit from several threads
at the same time. Thanks to the WHERE condition only one of them wins.
@seanlinsley seanlinsley mentioned this pull request Apr 27, 2014
@seanlinsley
Copy link
Contributor

Closing this in favor of #2332. Deleting the branch via the Github UI so we can restore it later if needed.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants