Loading django/db/__init__.py +11 −2 Original line number Diff line number Diff line Loading @@ -42,8 +42,17 @@ backend = load_backend(connection.settings_dict['ENGINE']) # Register an event that closes the database connection # when a Django request is finished. def close_connection(**kwargs): for conn in connections.all(): conn.close() # Avoid circular imports from django.db import transaction for conn in connections: try: transaction.abort(conn) connections[conn].close() except Exception: # The connection's state is unknown, so it has to be # abandoned. This could happen for example if the network # connection has a failure. del connections[conn] signals.request_finished.connect(close_connection) # Register an event that resets connection.queries Loading django/db/backends/__init__.py +11 −0 Original line number Diff line number Diff line Loading @@ -83,6 +83,17 @@ class BaseDatabaseWrapper(object): return self.cursor().execute(self.ops.savepoint_commit_sql(sid)) def abort(self): """ Roll back any ongoing transaction and clean the transaction state stack. """ if self._dirty: self._rollback() self._dirty = False while self.transaction_state: self.leave_transaction_management() def enter_transaction_management(self, managed=True): """ Enters transaction management for a running thread. It must be balanced with Loading django/db/transaction.py +15 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,21 @@ class TransactionManagementError(Exception): """ pass def abort(using=None): """ Roll back any ongoing transactions and clean the transaction management state of the connection. This method is to be used only in cases where using balanced leave_transaction_management() calls isn't possible. For example after a request has finished, the transaction state isn't known, yet the connection must be cleaned up for the next request. """ if using is None: using = DEFAULT_DB_ALIAS connection = connections[using] connection.abort() def enter_transaction_management(managed=True, using=None): """ Enters transaction management for a running thread. It must be balanced with Loading django/db/utils.py +3 −0 Original line number Diff line number Diff line Loading @@ -97,6 +97,9 @@ class ConnectionHandler(object): def __setitem__(self, key, value): setattr(self._connections, key, value) def __delitem__(self, key): delattr(self._connections, key) def __iter__(self): return iter(self.databases) Loading django/middleware/transaction.py +20 −1 Original line number Diff line number Diff line Loading @@ -15,6 +15,10 @@ class TransactionMiddleware(object): def process_exception(self, request, exception): """Rolls back the database and leaves transaction management""" if transaction.is_dirty(): # This rollback might fail because of network failure for example. # If rollback isn't possible it is impossible to clean the # connection's state. So leave the connection in dirty state and # let request_finished signal deal with cleaning the connection. transaction.rollback() transaction.leave_transaction_management() Loading @@ -22,6 +26,21 @@ class TransactionMiddleware(object): """Commits and leaves transaction management.""" if transaction.is_managed(): if transaction.is_dirty(): # Note: it is possible that the commit fails. If the reason is # closed connection or some similar reason, then there is # little hope to proceed nicely. However, in some cases ( # deferred foreign key checks for exampl) it is still possible # to rollback(). try: transaction.commit() except Exception: # If the rollback fails, the transaction state will be # messed up. It doesn't matter, the connection will be set # to clean state after the request finishes. And, we can't # clean the state here properly even if we wanted to, the # connection is in transaction but we can't rollback... transaction.rollback() transaction.leave_transaction_management() raise transaction.leave_transaction_management() return response Loading
django/db/__init__.py +11 −2 Original line number Diff line number Diff line Loading @@ -42,8 +42,17 @@ backend = load_backend(connection.settings_dict['ENGINE']) # Register an event that closes the database connection # when a Django request is finished. def close_connection(**kwargs): for conn in connections.all(): conn.close() # Avoid circular imports from django.db import transaction for conn in connections: try: transaction.abort(conn) connections[conn].close() except Exception: # The connection's state is unknown, so it has to be # abandoned. This could happen for example if the network # connection has a failure. del connections[conn] signals.request_finished.connect(close_connection) # Register an event that resets connection.queries Loading
django/db/backends/__init__.py +11 −0 Original line number Diff line number Diff line Loading @@ -83,6 +83,17 @@ class BaseDatabaseWrapper(object): return self.cursor().execute(self.ops.savepoint_commit_sql(sid)) def abort(self): """ Roll back any ongoing transaction and clean the transaction state stack. """ if self._dirty: self._rollback() self._dirty = False while self.transaction_state: self.leave_transaction_management() def enter_transaction_management(self, managed=True): """ Enters transaction management for a running thread. It must be balanced with Loading
django/db/transaction.py +15 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,21 @@ class TransactionManagementError(Exception): """ pass def abort(using=None): """ Roll back any ongoing transactions and clean the transaction management state of the connection. This method is to be used only in cases where using balanced leave_transaction_management() calls isn't possible. For example after a request has finished, the transaction state isn't known, yet the connection must be cleaned up for the next request. """ if using is None: using = DEFAULT_DB_ALIAS connection = connections[using] connection.abort() def enter_transaction_management(managed=True, using=None): """ Enters transaction management for a running thread. It must be balanced with Loading
django/db/utils.py +3 −0 Original line number Diff line number Diff line Loading @@ -97,6 +97,9 @@ class ConnectionHandler(object): def __setitem__(self, key, value): setattr(self._connections, key, value) def __delitem__(self, key): delattr(self._connections, key) def __iter__(self): return iter(self.databases) Loading
django/middleware/transaction.py +20 −1 Original line number Diff line number Diff line Loading @@ -15,6 +15,10 @@ class TransactionMiddleware(object): def process_exception(self, request, exception): """Rolls back the database and leaves transaction management""" if transaction.is_dirty(): # This rollback might fail because of network failure for example. # If rollback isn't possible it is impossible to clean the # connection's state. So leave the connection in dirty state and # let request_finished signal deal with cleaning the connection. transaction.rollback() transaction.leave_transaction_management() Loading @@ -22,6 +26,21 @@ class TransactionMiddleware(object): """Commits and leaves transaction management.""" if transaction.is_managed(): if transaction.is_dirty(): # Note: it is possible that the commit fails. If the reason is # closed connection or some similar reason, then there is # little hope to proceed nicely. However, in some cases ( # deferred foreign key checks for exampl) it is still possible # to rollback(). try: transaction.commit() except Exception: # If the rollback fails, the transaction state will be # messed up. It doesn't matter, the connection will be set # to clean state after the request finishes. And, we can't # clean the state here properly even if we wanted to, the # connection is in transaction but we can't rollback... transaction.rollback() transaction.leave_transaction_management() raise transaction.leave_transaction_management() return response