All pastes #627570 Raw Edit

fix for runInteraction

public python v1 · immutable
·published 2007-07-20 12:27 UTC
rendered paste body
"""Database access helpers"""from twisted.enterprise import adbapifrom twisted.internet import deferfrom twisted.python.failure import Failureimport configimport _mysql_exceptionsfrom twisted.python import logclass DbAccess(object):    """    Database access module, that wraps ConnectionPool in singleton pattern    and offers it as decorator    """    _instance=None    _retryCount=0    def __init__(self):        """        Not to be called manually, but through instance method        """        self.pool=adbapi.ConnectionPool(config.dbapi,                                        host=config.dbhost,                                        db=config.dbname,                                        user=config.dbuser,                                        passwd=config.dbpass,                                        )    @classmethod    def instance(klass):        """        Obtain a DbAccess instance / signleton pattern        """        if klass._instance is None:            klass._instance=klass()        return klass._instance        @classmethod    def newinstance(klass):        """        Create a new instance and enable it as signleton        """        klass._instance=None        return klass.instance()    @classmethod        def run(klass,f,*args,**kwargs):        """        A decorator function that runs function from adbapi's runInteraction        encodes all type 'unicode' objects passed as arguments to the function         into 'str'        Example:                        @dba.run        def doStuff(cursor,...):           cursor.execute(....)                   @return defer.Deferred        """        pool=klass.instance().pool                      def _run(*args,**kwargs):            for k,v in kwargs.items():                if type(v)==unicode:                    kwargs[k]=v.encode('utf-8')            nargs=[]                    for x in args:                if type(x)==unicode:                    nargs.append(x.encode('utf-8'))                            else:                    nargs.append(x)                        d=pool.runInteraction(f,*nargs,**kwargs)            assert isinstance(d,defer.Deferred)            return d.addErrback(klass._handleError,f,*nargs,**kwargs)                    return _run        @classmethod    def _handleError(klass,failure,f,*args,**kwargs):        """        Handle OperationalError,2006 - MySQLd has gone away        Reconnect to server and retry 3 times        """         assert isinstance(failure,Failure)        failure.trap(_mysql_exceptions.OperationalError)        e=failure.value                assert isinstance(e,_mysql_exceptions.OperationalError)        code=e.args[0]                if code==2006: # Server gone away - idle connection dropped, retry            log.msg("Mysql gone away, reconnecting",system="DbAccess")            if klass._retryCount<3:                klass._retryCount+=1                klass.newinstance()                return klass.run(f)(*args,**kwargs).addCallback(klass._resetRetryCount)            else:                log.msg("Giving up retries",system="DbAccess")                raise e            @classmethod    def _resetRetryCount(klass,result):        """        Reset retry count for OperationalError/2006 handling        """        klass._retryCount=0        return result