Skip to content

Commit

Permalink
Merge pull request #11 from jzuech3/master
Browse files Browse the repository at this point in the history
Add an ExecuteLastObjectDataManager that attempts to execute after ot…
  • Loading branch information
jamadden committed Apr 17, 2017
2 parents 051b180 + 26fcdab commit 3c68992
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 5 deletions.
5 changes: 3 additions & 2 deletions CHANGES.rst
Expand Up @@ -2,10 +2,11 @@
Changes
========

1.0.1 (unreleased)
1.1 (unreleased)
------------------

- Nothing changed yet.
- Add a new ObjectDataManager that will attempt to execute after
other ObjectDataManagers.


1.0.0 (2016-07-28)
Expand Down
25 changes: 23 additions & 2 deletions src/nti/transactions/tests/test_transaction.py
Expand Up @@ -12,18 +12,23 @@
#pylint: disable=W0212,R0904

import unittest

from hamcrest import assert_that
from hamcrest import is_
from hamcrest import calling
from hamcrest import raises
from hamcrest import contains

import fudge

from ..transactions import _do_commit
from ..transactions import TransactionLoop
from ..interfaces import CommitFailedError
from ..interfaces import AbortFailedError

from ..transactions import do
from ..transactions import do_near_end
from ..transactions import _do_commit
from ..transactions import TransactionLoop

import transaction
from transaction.interfaces import TransientError

Expand Down Expand Up @@ -218,3 +223,19 @@ def handler():

loop = Loop(handler)
assert_that(calling(loop), raises(AbortFailedError))

class TestDataManagers(unittest.TestCase):

def test_data_manager_sorting(self):
results = []
def test_call(x):
results.append(x)

# The managers will execute in order added (since identical),
# except for the one that requests to go last.
manager1 = do(call=test_call, args=(0,))
manager2 = do(call=test_call, args=(1,))
manager_post = do_near_end(call=test_call, args=(10,))
manager3 = do(call=test_call, args=(2,))
transaction.commit()
assert_that(results, contains(0, 1, 2, 10))
32 changes: 31 additions & 1 deletion src/nti/transactions/transactions.py
Expand Up @@ -196,6 +196,24 @@ def rollback(self):
# anyway.
pass

class OrderedNearEndObjectDataManager(ObjectDataManager):
"""
A special extension of :class:`ObjectDataManager` that attempts to execute
after all other data managers have executed. This is useful when an
operation relies on the execution of other data managers.
.. versionadded:: 1.1
"""

def sortKey(self):
"""
Sort prepended with z's in an attempt to execute after other data
managers.
"""
parent_key = super(OrderedNearEndObjectDataManager, self).sortKey()
sort_str = str(self.target) if self.target is not None else str(self.callable)
return 'zzz%s:%s' % (sort_str, parent_key)

class _QueuePutDataManager(ObjectDataManager):
"""
A data manager that checks if the queue is full before putting.
Expand Down Expand Up @@ -233,10 +251,22 @@ def do(*args, **kwargs):
Establishes a IDataManager in the current transaction.
See :class:`ObjectDataManager` for the possible arguments.
"""
result = ObjectDataManager(*args, **kwargs)
klass = kwargs.pop('datamanager_class', ObjectDataManager)
result = klass(*args, **kwargs)
transaction.get().join(result)
return result

def do_near_end(*args, **kwargs):
"""
Establishes a IDataManager in the current transaction that will attempt to
execute *after* all other DataManagers have had their say.
See :class:`ObjectDataManager` for the possible arguments.
.. versionadded:: 1.1
"""
kwargs['datamanager_class'] = OrderedNearEndObjectDataManager
return do(*args, **kwargs)

def _do_commit(tx, description, long_commit_duration):
exc_info = sys.exc_info()
try:
Expand Down

0 comments on commit 3c68992

Please sign in to comment.