3

Context:cherrypy session currently locks on request start and releases the lock when the request ends. Hence concurrent requests are processed serially and getting blocked.

Is it possible to extend a class, overwrite a few methods where the new methods call the parent method and then monkey patch the result?

Example:

from cherrypy.lib import sessions
class LockingSession(sessions.RamSession):
    def get(self, *args, **kwargs):
        # acquire lock
        super(LockingSession).get(*args, **kwargs)
        # release lock
sessions.RamSession = LockingSession

The example doesn't work - infinite loop :-)

Would this be the correct approach. Is this possible at all? If yes, how?

kev
  • 8,928
  • 14
  • 61
  • 103
  • I'm not sure about monkey patching, but I'd try inject your class into the `sessions` module instead of replacing existing one and then enable it in config. Look at this line https://github.com/cherrypy/cherrypy/blob/master/cherrypy/lib/sessions.py#L784 They pick class declared in module by name in config. You should probably use this. – webknjaz -- Слава Україні Jun 28 '16 at 13:32
  • Here's an example of custom session class with redis backend: https://bitbucket.org/webknjaz/blueberrypy-wk/src/cb2753de29c4ec0f1be00baf2e828b35e0939b47/src/blueberrypy/command.py?at=default&fileviewer=file-view-default#command.py-269:270 https://bitbucket.org/webknjaz/blueberrypy-wk/src/cb2753de29c4ec0f1be00baf2e828b35e0939b47/src/blueberrypy/session.py?at=default&fileviewer=file-view-default#session.py-33:91 – webknjaz -- Слава Україні Jun 28 '16 at 13:38
  • Didn't know about Mokey patching :) I know it as Aspect Oriented Programming. Maybe this thread can help: http://stackoverflow.com/questions/286958/any-aop-support-library-for-python – Johan Jun 28 '16 at 14:08
  • With `super()` or `super(LockingSession, self)` I'm getting: `>>> sessions.RamSession = LockingSession` `>>> t = sessions.RamSession()` `>>> t.get("A")` `[28/Jun/2016:10:33:54] ENGINE Started monitor thread 'Session cleanup'.` What error are you getting? You shouldn't be getting an infinite loop, since `self(LockingSession, [])` references an object pointer, not a name. – Poik Jun 28 '16 at 14:36
  • Wow. Missed that typo... `super(LockingSession, [...])` references a class descriptor reference (which is an object of type `super` in this case, but uses a reference to the original `type` object), not a name. – Poik Jun 28 '16 at 14:49
  • Hello @kev, I just want to inform you, that there's a new way of specifying session class available: https://github.com/cherrypy/cherrypy/pull/1495 – webknjaz -- Слава Україні Oct 01 '16 at 18:46
  • I know this is late, but I'm curious why not just patch the get function? – 1419636215 Dec 06 '19 at 18:47
  • So many comments, and still no answer to a smile question. lol – user64204 Mar 20 '23 at 14:45

1 Answers1

0

UPD (Oct 1, 2016):

This pull request (merged on Sep 4, 2016 and available for CherryPy >= 8.1) introduces a new way of specifying session class. Smth like this should serve your needs:

import cherrypy

class Root:
    ...

class LockingSession(sessions.RamSession):
    def get(self, *args, **kwargs):
        # acquire lock
        super(LockingSession).get(*args, **kwargs)
        # release lock

conf = {
    ...,
    'tools.sessions.storage_class': LockingSession,
    ...,
}

cherrypy.quickstart(Root(), '/', conf)

Old answer:

Following should work:

from cherrypy.lib import sessions
class LockingSession(sessions.RamSession):
    def get(self, *args, **kwargs):
        # acquire lock
        super(LockingSession).get(*args, **kwargs)
        # release lock

sessions.LockingSession = LockingSession