2

In attempting to implement automatic logout on the browser-side after 30 seconds of inactivity, we thought of creating a /heartbeat endpoint:

  • when the user moves the mouse or types any key, a javascript callback is scheduled after 10 seconds, to call PUT /heartbeat.
  • if a callback is already scheduled, the previous one is cancelled - this is done to avoid an "avalanche" of PUT /heartbeat when the user types and/or moves the mouse continuously (while e.g. writing content).
  • then, every 60 seconds, a GET /heartbeat is issued - that checks how much time has passed since the last time this user's session was 'updated'. We can do this by checking the content of the beaker session table. If more than 30 minutes have passed, the endpoint returns an appropriate indication to Javascript, so the user is automatically logged out in the browser.

This would work fine, except for one minor flaw - the GET /heartbeat updates the beaker session timestamp...

So, the question is - under Pyramid/Beaker, is there a way to create an endpoint that DOESN'T update the session timestamp?

WTK
  • 16,583
  • 6
  • 35
  • 45
ttsiodras
  • 10,602
  • 6
  • 55
  • 71
  • *if a callback is already scheduled, the previous one is cancelled* This way if user does something continuously you will never get hearbeat... – Piotr Dobrogost Sep 16 '15 at 11:23
  • @Piotr: If a user is doing something, then the backend is called because of his actions, so his session stays alive. – ttsiodras Sep 17 '15 at 10:44
  • *(...) this is done to avoid an "avalanche" of `PUT /heartbeat` when the user types and/or moves the mouse continuously* Do you really call backend when user is merely typing let alone moving mouse? – Piotr Dobrogost Sep 17 '15 at 11:32
  • :-) No, of course not. The point is that the user may do something that involves the backend (which means beaker/pyramid will mark the session and it remains alive) or he may be writing in our document editor (which doesn't invoke the backend, so his session may expire. The heartbeat is used to indicate that the user is alive, even though he hasn't called the backend (yet - to save his changes). Makes sense now? If he writes/moves the mouse, 10 seconds later a heartbeat will be sent, keeping the session alive. We don;t want this on every mousemove/keystroke, hence the throttling – ttsiodras Sep 17 '15 at 13:07

1 Answers1

2

What I did end up doing is I created my own BeakerSessionFactoryConfig, as well as session_factory_from_settings (that instantiates BeakerSessionFactoryConfig).

Then I modified what you can see here (a call to self.persist()) https://github.com/Pylons/pyramid_beaker/blob/6a62134bf99ff8d0836ccc0f6be557b816fa9987/pyramid_beaker/init.py#L32 to be a conditional operation based on if certain attribute is set on a request object.

This works because as long as .persists() isn't called, the session "last accessed" timestamp isn't updated in the database (or whatever other storage you're using).

WTK
  • 16,583
  • 6
  • 35
  • 45