def test_tasks_are_passed_along(self, queue_add_mock): """Ensure the list of tasks are passed along.""" from furious.context.context import _insert_tasks _insert_tasks(('A', 1, 'B', 'joe'), 'AbCd') queue_add_mock.assert_called_once_with(('A', 1, 'B', 'joe'), transactional=False)
def insert_tasks_ignore_duplicate_names(tasks, queue, *args, **kwargs): """Insert a batch of tasks into a specific queue. If a DuplicateTaskNameError is raised, loop through the tasks and insert the remaining, ignoring and logging the duplicate tasks. Returns the number of successfully inserted tasks. """ from google.appengine.api import taskqueue try: inserted = _insert_tasks(tasks, queue, *args, **kwargs) return inserted except taskqueue.DuplicateTaskNameError: # At least one task failed in our batch, attempt to re-insert the # remaining tasks. Named tasks can never be transactional. reinsert = _tasks_to_reinsert(tasks, transactional=False) count = len(reinsert) inserted = len(tasks) - count # Our subsequent task inserts should raise TaskAlreadyExistsError at # least once, but that will be swallowed by _insert_tasks. for task in reinsert: inserted += _insert_tasks([task], queue, *args, **kwargs) return inserted
def test_batches_get_split_TombstonedTaskError(self, queue_add_mock): """Ensure a batches get split and retried on TombstonedTaskErrors.""" from furious.context.context import _insert_tasks def raise_error(*args, **kwargs): from google.appengine.api import taskqueue raise taskqueue.TombstonedTaskError() queue_add_mock.side_effect = raise_error _insert_tasks(('A', 1, 'B'), 'AbCd') self.assertEqual(5, queue_add_mock.call_count)
def test_task_add_error_TombstonedTaskError(self, queue_add_mock): """Ensure a TombstonedTaskError doesn't get raised from add.""" from furious.context.context import _insert_tasks def raise_error(*args, **kwargs): from google.appengine.api import taskqueue raise taskqueue.TombstonedTaskError() queue_add_mock.side_effect = raise_error _insert_tasks(('A',), 'AbCd') queue_add_mock.assert_called_once_with(('A',), transactional=False)
def test_task_add_error_TombstonedTaskError(self, queue_add_mock): """Ensure a TombstonedTaskError doesn't get raised from add.""" from furious.context.context import _insert_tasks def raise_error(*args, **kwargs): from google.appengine.api import taskqueue raise taskqueue.TombstonedTaskError() queue_add_mock.side_effect = raise_error _insert_tasks(('A', ), 'AbCd') queue_add_mock.assert_called_once_with(('A', ), transactional=False)
def test_queue_name_is_honored(self, queue_mock): """Ensure the Queue is instantiated with the name.""" from furious.context.context import _insert_tasks inserted = _insert_tasks((None,), 'AbCd') queue_mock.assert_called_once_with(name='AbCd') self.assertEqual(1, inserted)
def test_no_tasks_doesnt_blow_up(self): """Ensure calling with an empty list doesn't blow up.""" from furious.context.context import _insert_tasks inserted = _insert_tasks((), 'A') self.assertEqual(0, inserted)
def test_tasks_are_passed_along(self, queue_add_mock): """Ensure the list of tasks are passed along.""" from furious.context.context import _insert_tasks inserted = _insert_tasks(("A", 1, "B", "joe"), "AbCd") queue_add_mock.assert_called_once_with(("A", 1, "B", "joe"), transactional=False) self.assertEqual(4, inserted)
def test_task_add_error_TransientError(self, queue_add_mock, mock_sleep): """Ensure a TransientError doesn't get raised from add.""" from furious.context.context import _insert_tasks from google.appengine.api import taskqueue queue_add_mock.side_effect = taskqueue.TransientError inserted = _insert_tasks(('A',), 'AbCd', retry_errors=False) queue_add_mock.assert_called_once_with(('A',), transactional=False) self.assertEqual(0, inserted)
def test_single_task_gets_retried(self, queue_add_mock, mock_sleep): """Ensure a single task failing causes a retry. """ from furious.context.context import _insert_tasks from google.appengine.api import taskqueue queue_add_mock.side_effect = (taskqueue.TransientError, None) inserted = _insert_tasks((taskqueue.Task('A'), ), 'AbCd') self.assertEqual(queue_add_mock.call_count, 2) self.assertEqual(inserted, 1)
def test_single_task_gets_retried(self, queue_add_mock, mock_sleep): """Ensure a single task failing causes a retry. """ from furious.context.context import _insert_tasks from google.appengine.api import taskqueue queue_add_mock.side_effect = (taskqueue.TransientError, None) inserted = _insert_tasks((taskqueue.Task('A'),), 'AbCd') self.assertEqual(queue_add_mock.call_count, 2) self.assertEqual(inserted, 1)
def test_task_add_error_TaskAlreadyExistsError(self, queue_add_mock): """Ensure a TaskAlreadyExistsError doesn't get raised from add.""" from furious.context.context import _insert_tasks def raise_error(*args, **kwargs): from google.appengine.api import taskqueue raise taskqueue.TaskAlreadyExistsError() queue_add_mock.side_effect = raise_error inserted = _insert_tasks(("A",), "AbCd") queue_add_mock.assert_called_once_with(("A",), transactional=False) self.assertEqual(0, inserted)
def test_batches_get_split_TransientError(self, queue_add_mock, mock_sleep): """Ensure TransientErrors retries once, and correctly returns the number of inserted tasks.""" from furious.context.context import _insert_tasks from google.appengine.api import taskqueue queue_add_mock.side_effect = (taskqueue.TransientError, None) tasks = (taskqueue.Task('A'), taskqueue.Task('1'), taskqueue.Task('B')) inserted = _insert_tasks(tasks, 'AbCd') self.assertEqual(2, queue_add_mock.call_count) self.assertEqual(3, inserted) self.assertEqual(mock_sleep.call_count, 1)
def test_batches_get_split_TombstonedTaskError(self, queue_add_mock): """Ensure a batches get split and retried on TombstonedTaskErrors.""" from furious.context.context import _insert_tasks from google.appengine.api import taskqueue def raise_error(*args, **kwargs): raise taskqueue.TombstonedTaskError() queue_add_mock.side_effect = raise_error tasks = (taskqueue.Task("A"), taskqueue.Task("1"), taskqueue.Task("B")) inserted = _insert_tasks(tasks, "AbCd") self.assertEqual(5, queue_add_mock.call_count) self.assertEqual(0, inserted)
def test_batches_get_split_BadTaskStateError(self, queue_add_mock): """Ensure a batches get split and retried on BadTaskStateErrors.""" from furious.context.context import _insert_tasks from google.appengine.api import taskqueue def raise_error(*args, **kwargs): raise taskqueue.BadTaskStateError() queue_add_mock.side_effect = raise_error tasks = (taskqueue.Task('A'), taskqueue.Task('1'), taskqueue.Task('B')) inserted = _insert_tasks(tasks, 'AbCd') self.assertEqual(5, queue_add_mock.call_count) self.assertEqual(0, inserted)
def test_batches_get_split_BadTaskStateError(self, queue_add_mock): """Ensure a batches get split and retried on BadTaskStateErrors.""" from furious.context.context import _insert_tasks def raise_error(*args, **kwargs): from google.appengine.api import taskqueue raise taskqueue.BadTaskStateError() queue_add_mock.side_effect = raise_error inserted = _insert_tasks(("A", 1, "B"), "AbCd") self.assertEqual(5, queue_add_mock.call_count) self.assertEqual(0, inserted)
def test_batches_get_split_dont_reinsert_enqueued(self, queue_add_mock): """Ensure a batch gets split and retried on error but only tasks which were not enqueued are retried. """ from furious.context.context import _insert_tasks from google.appengine.api import taskqueue def raise_error(*args, **kwargs): raise taskqueue.TombstonedTaskError() queue_add_mock.side_effect = raise_error tasks = (Mock(), taskqueue.Task('1'), taskqueue.Task('B')) tasks[0].was_enqueued = True inserted = _insert_tasks(tasks, 'AbCd') self.assertEqual(3, queue_add_mock.call_count) self.assertEqual(1, inserted)
def test_tasks_not_enqueued_get_retried(self, queue_add_mock, mock_sleep): """Ensure if a taskqueue add causes a TransientError, only the tasks which were not enqueued are retried. """ from furious.context.context import _insert_tasks from google.appengine.api import taskqueue queue_add_mock.side_effect = (taskqueue.TransientError, None) tasks = (Mock(), taskqueue.Task("1"), taskqueue.Task("B")) tasks[0].was_enqueued = True inserted = _insert_tasks(tasks, "AbCd") calls = [call(tasks, transactional=False), call([tasks[1], tasks[2]], transactional=False)] self.assertEqual(queue_add_mock.call_args_list, calls) self.assertEqual(inserted, 3)
def test_tasks_not_enqueued_get_retried(self, queue_add_mock, mock_sleep): """Ensure if a taskqueue add causes a TransientError, only the tasks which were not enqueued are retried. """ from furious.context.context import _insert_tasks from google.appengine.api import taskqueue queue_add_mock.side_effect = (taskqueue.TransientError, None) tasks = (Mock(), taskqueue.Task('1'), taskqueue.Task('B')) tasks[0].was_enqueued = True inserted = _insert_tasks(tasks, 'AbCd') calls = [ call(tasks, transactional=False), call([tasks[1], tasks[2]], transactional=False) ] self.assertEqual(queue_add_mock.call_args_list, calls) self.assertEqual(inserted, 3)