durusmail: quixote-users: Persistent Session Management with Durus
Persistent Session Management with Durus
2010-08-26
2010-08-26
2010-08-26
2010-08-26
2010-08-26
2010-08-27
2010-08-28
Persistent Session Management with Durus
Salman Haq
2010-08-26
Some new info included at the end:


On 08/26/2010 10:49 AM, Salman Haq wrote:
> |Hi,
>
> I'm developing an application using Quixote 2.6 and following the example in
altdemo.py pretty closely for persistent session management with Durus.
> The application is serving static files very unreliably. One in five requests
for a static file receive a HTTP 500 response code. Eg: if an html page embeds
50
> script or img tags, requests for about 10 of them will fail. For each of these
failed requests, the following traceback is received:
>
> Traceback (most recent call last):
> ||   File "/usr/lib/python2.4/site-packages/quixote2/publish.py", line 275, in
process_request
> ||     output = self.try_publish(request)
> ||   File "/usr/lib/python2.4/site-packages/quixote2/publish.py", line 255, in
try_publish
> ||     self.finish_successful_request()
> ||   File "/usr/lib/python2.4/site-packages/quixote2/publish.py", line 138, in
finish_successful_request||
> ||     self.session_manager.finish_successful_request()
> ||   File "/usr/lib/python2.4/site-packages/quixote2/session.py", line 388, in
finish_successful_request||
> ||     self.commit_changes(session)
> ||   File "/usr/lib/python2.4/site-packages/ACE_rms/auth/session.py", line 44,
in commit_changes
> ||     self.durus_connection.commit()
> ||   File "/usr/lib/python2.4/site-packages/durus/connection.py", line 254, in
commit
> ||     assert not self.invalid_oids, "still conflicted: missing abort()"
> ||AssertionError: still conflicted: missing abort()
>
> My application is running as a SCGI process behind Apache. Static files are
served by Quixote via the StaticDirectory class and not by Apache.
> The Durus server runs as a stand-alone process on localhost:2951 and a
connection object to it is created as follows:
>
> def publisher_factory ():
>      """ returns a quixote2 Publisher instance that publishes
>      the RootDirectory with persistent session management support.
>      """
>      conn = Connection(ClientStorage("127.0.0.1", 2951))
>      session_manager = DurusSessionManager(conn)
>      return Publisher(RootDirectory(), session_manager=session_manager,
display_exceptions='plain')
>
>
> The application sub-classes SessionManager and Session exactly as described in
the snippet below:
>
> ----
>
> from quixote2.session import Session, SessionManager
> from durus.persistent import Persistent
> from durus.persistent_dict import PersistentDict
>
> class PersistentSession (Session, Persistent):
>      """ Persistent version of default quixote Session class.
>      This class can be overridden if desired.
>      """
>      pass
>
> class DurusSessionManager (SessionManager):
>      """ Loads/stores quixote sessions from/to a Durus db.
>      Overrides forget_changes() and commit_changes() as described in quixote
>      docs and altdemo.py.
>      """
>
>      def __init__ (self, durus_connection, session_class=PersistentSession):
>          """ Load sessions from the durus db and init the SessionManager.
>          (inst, class) : inst
>          durus_connection: a Connection object to a Durus db.
>          session_class: session class to use (must override PeristentSession).
>          """
>          self.durus_connection = durus_connection
>          root = self.durus_connection.get_root()
>          sessions = root.get('auth.sessions', None)
>
>          if not sessions:
>              sessions = PersistentDict()
>              root['auth.sessions'] = sessions
>              self.durus_connection.commit()
>
>          SessionManager.__init__(self,
>                                  session_class=session_class,
>                                  session_mapping=sessions)
>
>      def forget_changes (self, session):
>          self.durus_connection.abort()
>
>      def commit_changes (self, session):
>          self.durus_connection.commit()
>
> -----
>
> Can anyone tell me why my Durus database thinks it's in a conflicted state?
>
> Thank you,
> Salman
> |||

Requests for static files are not the only ones that are likely to fail.
AJAX requests also tend to cause HTTP 500. Again, the failures are
unpredictable,
but usually one in a group of three or four simultaneous AJAX requests
by the browser can fail.

And the AssertionError mentioned above is not the only error raised by
the application. I have noticed a WriteConflictError too, albeit less
frequently:

Traceback (most recent call last):

       File "/usr/lib/python2.4/site-packages/quixote2/publish.py", line 275, in
process_request
         output = self.try_publish(request)
       File "/usr/lib/python2.4/site-packages/quixote2/publish.py", line 255, in
try_publish
         self.finish_successful_request()
       File "/usr/lib/python2.4/site-packages/quixote2/publish.py", line 138, in
finish_successful_request
         self.session_manager.finish_successful_request()
       File "/usr/lib/python2.4/site-packages/quixote2/session.py", line 388, in
finish_successful_request
         self.commit_changes(session)
       File "/usr/lib/python2.4/site-packages/ACE_rms/auth/session.py", line 45,
in commit_changes
         self.durus_connection.commit()
       File "/usr/lib/python2.4/site-packages/durus/connection.py", line 273, in
commit
         self.storage.end(self._handle_invalidations)
       File "/usr/lib/python2.4/site-packages/durus/client_storage.py", line 82,
in end
         handle_invalidations(oid_list)
       File "/usr/lib/python2.4/site-packages/durus/connection.py", line 303, in
_handle_invalidations
         raise WriteConflictError(conflicts)
     WriteConflictError: oids=[2]

I'm still learning Durus, but I suspect quite a few people on this list
are familiar with its internals.

Thanks,
Salman

reply