Merge "Make it possible to opt out of nested transactions"
This commit is contained in:
commit
684c1e7c5b
|
@ -71,8 +71,9 @@ class Transaction(object):
|
|||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class API(object):
|
||||
def __init__(self):
|
||||
def __init__(self, nested_transactions=True):
|
||||
# Mapping between a (green)thread and its transaction.
|
||||
self._nested_txns = nested_transactions
|
||||
self._nested_txns_map = {}
|
||||
|
||||
@abc.abstractmethod
|
||||
|
@ -88,17 +89,23 @@ class API(object):
|
|||
"""
|
||||
|
||||
@contextlib.contextmanager
|
||||
def transaction(self, check_error=False, log_errors=True, **kwargs):
|
||||
def transaction(self, check_error=False, log_errors=True, nested=True,
|
||||
**kwargs):
|
||||
"""Create a transaction context.
|
||||
|
||||
:param check_error: Allow the transaction to raise an exception?
|
||||
:type check_error: bool
|
||||
:param log_errors: Log an error if the transaction fails?
|
||||
:type log_errors: bool
|
||||
:param nested: Allow nested transactions be merged into one txn
|
||||
:type nested: bool
|
||||
:returns: Either a new transaction or an existing one.
|
||||
:rtype: :class:`Transaction`
|
||||
"""
|
||||
cur_thread_id = thread.get_ident()
|
||||
# ojbect() is unique, so if we are not nested, this will always result
|
||||
# in a KeyError on lookup and so a unique Transaction
|
||||
nested = nested and self._nested_txns
|
||||
cur_thread_id = thread.get_ident() if nested else object()
|
||||
|
||||
try:
|
||||
yield self._nested_txns_map[cur_thread_id]
|
||||
|
|
|
@ -26,8 +26,8 @@ class Backend(object):
|
|||
lookup_table = {}
|
||||
ovsdb_connection = None
|
||||
|
||||
def __init__(self, connection):
|
||||
super(Backend, self).__init__()
|
||||
def __init__(self, connection, **kwargs):
|
||||
super(Backend, self).__init__(**kwargs)
|
||||
self.start_connection(connection)
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -33,3 +33,10 @@ class TransactionTestCase(base.TestCase):
|
|||
transaction = impl_idl.OvsVsctlTransaction(mock.sentinel,
|
||||
mock.Mock(), 0)
|
||||
transaction.post_commit(mock.Mock())
|
||||
|
||||
|
||||
class TestOvsdbIdl(base.TestCase):
|
||||
def test_nested_txns(self):
|
||||
conn = mock.MagicMock()
|
||||
api = impl_idl.OvsdbIdl(conn, nested_transactions=False)
|
||||
self.assertFalse(api._nested_txns)
|
||||
|
|
|
@ -65,7 +65,9 @@ class FakeTransaction(object):
|
|||
|
||||
class TestingAPI(api.API):
|
||||
def create_transaction(self, check_error=False, log_errors=True, **kwargs):
|
||||
return FakeTransaction()
|
||||
txn = FakeTransaction()
|
||||
mock.patch.object(txn, 'commit').start()
|
||||
return txn
|
||||
|
||||
|
||||
TestingAPI.__abstractmethods__ = set()
|
||||
|
@ -75,7 +77,6 @@ class TransactionTestCase(base.TestCase):
|
|||
def setUp(self):
|
||||
super(TransactionTestCase, self).setUp()
|
||||
self.api = TestingAPI()
|
||||
mock.patch.object(FakeTransaction, 'commit').start()
|
||||
self.useFixture(GreenThreadingFixture())
|
||||
|
||||
def test_transaction_nested(self):
|
||||
|
@ -84,6 +85,21 @@ class TransactionTestCase(base.TestCase):
|
|||
self.assertIs(txn1, txn2)
|
||||
txn1.commit.assert_called_once_with()
|
||||
|
||||
def test_transaction_nested_false(self):
|
||||
with self.api.transaction(nested=False) as txn1:
|
||||
with self.api.transaction() as txn2:
|
||||
self.assertIsNot(txn1, txn2)
|
||||
txn1.commit.assert_called_once_with()
|
||||
txn2.commit.assert_called_once_with()
|
||||
|
||||
def test_api_level_transaction_nested_fales(self):
|
||||
api = TestingAPI(nested_transactions=False)
|
||||
with api.transaction() as txn1:
|
||||
with api.transaction() as txn2:
|
||||
self.assertIsNot(txn1, txn2)
|
||||
txn1.commit.assert_called_once_with()
|
||||
txn2.commit.assert_called_once_with()
|
||||
|
||||
def test_transaction_no_nested_transaction_after_error(self):
|
||||
class TestException(Exception):
|
||||
pass
|
||||
|
|
Loading…
Reference in New Issue