mirror of https://github.com/django/django.git
Fixed #21202 -- Maintained atomicity when the server disconnects.
Thanks intgr for the report. This commit doesn't include a test because I don't know how to emulate a database disconnection in a cross-database compatible way. Also simplified a 'backends' test that was constrained by this problem.
This commit is contained in:
parent
25860096f9
commit
8176150850
|
@ -2,7 +2,7 @@ from functools import wraps
|
||||||
|
|
||||||
from django.db import (
|
from django.db import (
|
||||||
connections, DEFAULT_DB_ALIAS,
|
connections, DEFAULT_DB_ALIAS,
|
||||||
DatabaseError, ProgrammingError)
|
DatabaseError, Error, ProgrammingError)
|
||||||
from django.utils.decorators import available_attrs
|
from django.utils.decorators import available_attrs
|
||||||
|
|
||||||
|
|
||||||
|
@ -224,7 +224,12 @@ class Atomic(object):
|
||||||
try:
|
try:
|
||||||
connection.commit()
|
connection.commit()
|
||||||
except DatabaseError:
|
except DatabaseError:
|
||||||
connection.rollback()
|
try:
|
||||||
|
connection.rollback()
|
||||||
|
except Error:
|
||||||
|
# Error during rollback means the connection was
|
||||||
|
# closed. Clean up in case the server dropped it.
|
||||||
|
connection.close()
|
||||||
raise
|
raise
|
||||||
else:
|
else:
|
||||||
# This flag will be set to True again if there isn't a savepoint
|
# This flag will be set to True again if there isn't a savepoint
|
||||||
|
@ -245,7 +250,12 @@ class Atomic(object):
|
||||||
connection.needs_rollback = True
|
connection.needs_rollback = True
|
||||||
else:
|
else:
|
||||||
# Roll back transaction
|
# Roll back transaction
|
||||||
connection.rollback()
|
try:
|
||||||
|
connection.rollback()
|
||||||
|
except Error:
|
||||||
|
# Error during rollback means the connection was
|
||||||
|
# closed. Clean up in case the server dropped it.
|
||||||
|
connection.close()
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
# Outermost block exit when autocommit was enabled.
|
# Outermost block exit when autocommit was enabled.
|
||||||
|
|
|
@ -664,13 +664,6 @@ class BackendTestCase(TestCase):
|
||||||
self.assertIsInstance(cursor, CursorWrapper)
|
self.assertIsInstance(cursor, CursorWrapper)
|
||||||
self.assertTrue(cursor.closed)
|
self.assertTrue(cursor.closed)
|
||||||
|
|
||||||
|
|
||||||
class IsUsableTests(TransactionTestCase):
|
|
||||||
# Avoid using a regular TestCase because Django really dislikes closing
|
|
||||||
# the database connection inside a transaction at this point (#21202).
|
|
||||||
|
|
||||||
available_apps = []
|
|
||||||
|
|
||||||
# Unfortunately with sqlite3 the in-memory test database cannot be closed.
|
# Unfortunately with sqlite3 the in-memory test database cannot be closed.
|
||||||
@skipUnlessDBFeature('test_db_allows_multiple_connections')
|
@skipUnlessDBFeature('test_db_allows_multiple_connections')
|
||||||
def test_is_usable_after_database_disconnects(self):
|
def test_is_usable_after_database_disconnects(self):
|
||||||
|
|
Loading…
Reference in New Issue