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
Thanks Gabor! That works.

Neither the Durus README file nor the online FAQs mention anything about
re-try logic.

Salman

On 08/26/2010 02:01 PM, Gabor Vitez wrote:
> Hi!
>
> As far as I can tell, this is normal behaviour with Durus; I'd suggest
> wrapping every function that reads or writes durus with something like
> this:
>
> def writetransaction(func):
>   """wrap writers with this"""
>   def wrapper(*args, **kw):
>     conn=dbconn.get_db()
>     #bail after 1000 failures
>     for dummy1 in xrange(1000):
>       try:
>         results=func(*args,**kw)
>         conn.commit()
>         return results
>       except ConflictError:
>         pass
>       conn.abort()
>     raise ConflictError
>   return wrapper
>
> def readtransaction(func):
>   """wrap readers with this"""
>   def wrapper(*args, **kw):
>     conn=dbconn.get_db()
>     for dummy1 in xrange(1000):
>       try:
>         return func(*args,**kw)
>       except ConflictError:
>         pass
>       conn.abort()
>     raise ConflictError
>   return wrapper
>
>
> dbconn is the global database connection object
>
> Best,
> Gábor
>
> On Thu, Aug 26, 2010 at 5:23 PM, Salman Haq  > wrote:
>
>     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
>
>
>     _______________________________________________
>     Quixote-users mailing list
>     Quixote-users@mems-exchange.org
>     
>     http://mail.mems-exchange.org/mailman/listinfo/quixote-users
>
>

reply