diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2007-04-02 22:03:06 +0000 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2007-04-02 22:03:06 +0000 |
| commit | c416dad6c652262bafbb137e6412054481db8e2f (patch) | |
| tree | 08d1b606fbe657011dd014ab4cd7d68165f7f063 /lib/sqlalchemy/pool.py | |
| parent | cdceb3c3714af707bfe3ede10af6536eaf529ca8 (diff) | |
| download | sqlalchemy-c416dad6c652262bafbb137e6412054481db8e2f.tar.gz | |
- merged the patch from #516 + fixes
- improves the framework for auto-invalidation of connections that have
lost their underlying database - the error catching/invalidate
step is totally moved to the connection pool.
- added better condition checking for do_rollback() and do_commit() including
SQLError excepetion wrapping
Diffstat (limited to 'lib/sqlalchemy/pool.py')
| -rw-r--r-- | lib/sqlalchemy/pool.py | 68 |
1 files changed, 47 insertions, 21 deletions
diff --git a/lib/sqlalchemy/pool.py b/lib/sqlalchemy/pool.py index 8d559aff5..0b1ac2630 100644 --- a/lib/sqlalchemy/pool.py +++ b/lib/sqlalchemy/pool.py @@ -125,7 +125,8 @@ class Pool(object): False, then no cursor processing occurs upon checkin. """ - def __init__(self, creator, recycle=-1, echo=None, use_threadlocal=False, auto_close_cursors=True, disallow_open_cursors=False): + def __init__(self, creator, recycle=-1, echo=None, use_threadlocal=False, auto_close_cursors=True, + disallow_open_cursors=False, disconnect_checker=None): self.logger = logging.instance_logger(self) self._threadconns = weakref.WeakValueDictionary() self._creator = creator @@ -134,6 +135,10 @@ class Pool(object): self.auto_close_cursors = auto_close_cursors self.disallow_open_cursors = disallow_open_cursors self.echo = echo + if disconnect_checker: + self.disconnect_checker = disconnect_checker + else: + self.disconnect_checker = lambda x: False echo = logging.echo_property() def unique_connection(self): @@ -183,8 +188,11 @@ class _ConnectionRecord(object): self.__pool.log("Closing connection %s" % repr(self.connection)) self.connection.close() - def invalidate(self): - self.__pool.log("Invalidate connection %s" % repr(self.connection)) + def invalidate(self, e=None): + if e is not None: + self.__pool.log("Invalidate connection %s (reason: %s:%s)" % (repr(self.connection), e.__class__.__name__, str(e))) + else: + self.__pool.log("Invalidate connection %s" % repr(self.connection)) self.__close() self.connection = None @@ -226,7 +234,7 @@ class _ConnectionFairy(object): def __init__(self, pool): self._threadfairy = _ThreadFairy(self) self._cursors = weakref.WeakKeyDictionary() - self.__pool = pool + self._pool = pool self.__counter = 0 try: self._connection_record = pool.get() @@ -235,15 +243,17 @@ class _ConnectionFairy(object): self.connection = None # helps with endless __getattr__ loops later on self._connection_record = None raise - if self.__pool.echo: - self.__pool.log("Connection %s checked out from pool" % repr(self.connection)) + if self._pool.echo: + self._pool.log("Connection %s checked out from pool" % repr(self.connection)) + + _logger = property(lambda self: self._pool.logger) - _logger = property(lambda self: self.__pool.logger) - - def invalidate(self): + is_valid = property(lambda self:self.connection is not None) + + def invalidate(self, e=None): if self.connection is None: raise exceptions.InvalidRequestError("This connection is closed") - self._connection_record.invalidate() + self._connection_record.invalidate(e=e) self.connection = None self._cursors = None self._close() @@ -253,7 +263,7 @@ class _ConnectionFairy(object): c = self.connection.cursor(*args, **kwargs) return _CursorFairy(self, c) except Exception, e: - self.invalidate() + self.invalidate(e=e) raise def __getattr__(self, key): @@ -282,21 +292,21 @@ class _ConnectionFairy(object): if self._cursors is not None: # cursors should be closed before connection is returned to the pool. some dbapis like # mysql have real issues if they are not. - if self.__pool.auto_close_cursors: + if self._pool.auto_close_cursors: self.close_open_cursors() - elif self.__pool.disallow_open_cursors: + elif self._pool.disallow_open_cursors: if len(self._cursors): raise exceptions.InvalidRequestError("This connection still has %d open cursors" % len(self._cursors)) if self.connection is not None: try: self.connection.rollback() - except: + except Exception, e: if self._connection_record is not None: - self._connection_record.invalidate() + self._connection_record.invalidate(e=e) if self._connection_record is not None: - if self.__pool.echo: - self.__pool.log("Connection %s being returned to pool" % repr(self.connection)) - self.__pool.return_conn(self) + if self._pool.echo: + self._pool.log("Connection %s being returned to pool" % repr(self.connection)) + self._pool.return_conn(self) self.connection = None self._connection_record = None self._threadfairy = None @@ -305,11 +315,27 @@ class _ConnectionFairy(object): class _CursorFairy(object): def __init__(self, parent, cursor): self.__parent = parent - self.__parent._cursors[self]=True + self.__parent._cursors[self] = True self.cursor = cursor - def invalidate(self): - self.__parent.invalidate() + def execute(self, *args, **kwargs): + try: + self.cursor.execute(*args, **kwargs) + except Exception, e: + if self.__parent._pool.disconnect_checker(e): + self.invalidate(e=e) + raise + + def executemany(self, *args, **kwargs): + try: + self.cursor.executemany(*args, **kwargs) + except Exception, e: + if self.__parent._pool.disconnect_checker(e): + self.invalidate(e=e) + raise + + def invalidate(self, e=None): + self.__parent.invalidate(e=e) def close(self): if self in self.__parent._cursors: |
