Example #1
0
 def test_fails_import_non_taskified_functions(self):
     """Consumer raises when trying to import a function not decorated with
     @taskify.
     """
     consumer = Consumer()
     self.assertRaises(TaskLoadingError, consumer.import_taskified_function,
                       'tests.fixtures.naked_function')
Example #2
0
 def test_fails_import_function_syntax_error(self):
     """Consumer raises when trying to import a function with a Python
     syntax error.
     """
     consumer = Consumer()
     self.assertRaises(TaskLoadingError, consumer.import_taskified_function,
                       'tests.fixtures_broken.broken_function')
Example #3
0
 def test_fails_import_non_existing_module(self):
     """Consumer raises when trying to import a function from a non-existing
     module.
     """
     consumer = Consumer()
     self.assertRaises(TaskLoadingError, consumer.import_taskified_function,
                       'tests.foobar.nope')
Example #4
0
    def test_consumer_logs_cleaned_backtrace(self):
        """Consumer will log catched exceptions with internal frames removed
        from the backtrace."""
        create_task(function_name='tests.fixtures.failing_alphabet',
                    max_retries=0)

        consumer = Consumer()

        with self.assertLogs('taskq', level='ERROR') as context_manager:
            consumer.execute_tasks()
            output = ''.join(context_manager.output)
            lines = output.splitlines()

        # First line is our custom message
        self.assertIn('ValueError', lines[0])
        self.assertIn('I don\'t know what comes after "d"', lines[0])

        # Skip the first line (our message) and the second one ("Traceback
        # (most recent call last)")
        lines = lines[2:]

        # Only check the even lines (containing the filename, line and function name)
        relevant_lines = [l for i, l in enumerate(lines) if i % 2 == 0]

        # Check that we are getting the expected function names in the traceback
        expected_functions = [
            '_protected_call', 'failing_alphabet', 'a', 'b', 'c', 'd'
        ]
        for i, expected_function in enumerate(expected_functions):
            self.assertIn(expected_function, relevant_lines[i])
Example #5
0
    def test_consumer_will_catch_task_exceptions(self):
        """Consumer will catch and log exceptions raised by the tasks."""
        task = create_task(function_name='tests.fixtures.failing',
                           max_retries=0)

        consumer = Consumer()
        consumer.execute_tasks()

        task.refresh_from_db()
        self.assertEqual(task.status, Task.STATUS_FAILED)
Example #6
0
    def test_consumer_run_due_task(self):
        """Consumer will run task at or after their due date."""
        due_at = now() - timedelta(milliseconds=100)
        task = create_task(due_at=due_at)

        consumer = Consumer()
        consumer.execute_tasks()

        task.refresh_from_db()
        self.assertEqual(task.status, Task.STATUS_SUCCESS)
Example #7
0
    def test_consumer_task_timeout(self):
        """Consumer will abort a task if it exceeds the timeout."""
        task = create_task(function_name='tests.fixtures.never_return',
                           timeout=timedelta(seconds=2))

        consumer = Consumer()
        consumer.execute_tasks()

        task.refresh_from_db()
        self.assertEqual(task.status, Task.STATUS_FAILED)
Example #8
0
    def test_consumer_wont_load_not_taskified_function(self):
        """Consumer will refuse to load a regular function not decorated with
        @taskify.
        """
        task = create_task(function_name='tests.fixtures.naked_function', )

        consumer = Consumer()
        consumer.execute_tasks()

        task.refresh_from_db()
        self.assertEqual(task.status, Task.STATUS_FAILED)
Example #9
0
    def test_consumer_run_self_cancelling_task(self):
        """Consumer will run a self-cancelling task only once."""
        due_at = now() - timedelta(milliseconds=100)
        task = create_task(function_name='tests.fixtures.self_cancelling',
                           due_at=due_at)

        consumer = Consumer()
        consumer.execute_tasks()

        task.refresh_from_db()
        self.assertEqual(task.status, Task.STATUS_CANCELED)
Example #10
0
    def test_consumer_logs_task_started(self):
        """Consumer will log that a task has started."""
        due_at = now() - timedelta(milliseconds=100)
        task = create_task(due_at=due_at)

        consumer = Consumer()
        with self.assertLogs('taskq', level='INFO') as context_manager:
            consumer.execute_tasks()
            output = ''.join(context_manager.output)

        self.assertIn(task.uuid, output)
        self.assertIn('Started', output)
Example #11
0
    def test_consumer_will_retry_after_task_error(self):
        """Consumer will catch the tasks error and retry to run the task
        later.
        """
        task = create_task(function_name='tests.fixtures.failing',
                           max_retries=3)

        consumer = Consumer()
        consumer.execute_tasks()

        task.refresh_from_db()
        self.assertEqual(task.status, Task.STATUS_QUEUED)
        self.assertEqual(task.retries, 1)
Example #12
0
    def test_consumer_logs_task_started_nth_rety(self):
        """Consumer will log that a task has started and is executing its nth rety."""
        due_at = now() - timedelta(milliseconds=100)
        task = create_task(function_name='tests.fixtures.failing',
                           due_at=due_at)

        consumer = Consumer()
        consumer.execute_tasks()

        with self.assertLogs('taskq', level='INFO') as context_manager:
            consumer.execute_tasks()
            output = ''.join(context_manager.output)

        self.assertIn(task.uuid, output)
        self.assertIn('Started (1st retry)', output)
Example #13
0
    def test_consumer_create_task_for_due_scheduled_task(self):
        """Consumer creates tasks for each scheduled task defined in settings.
        """
        consumer = Consumer()

        # Hack the due_at date to simulate the fact that the task was run once
        # already
        assert len(consumer._scheduler._tasks) == 1
        scheduled_task = consumer._scheduler._tasks[0]
        scheduled_task.due_at -= timedelta(days=1)

        consumer.create_scheduled_tasks()

        queued_tasks = Task.objects.filter(status=Task.STATUS_QUEUED).count()
        self.assertEqual(queued_tasks, 1)
Example #14
0
    def test_consumer_will_retry_at_most_max_retries_times(self):
        """Consumer will not retry the task more than task.max_retries times."""
        task = create_task(function_name='tests.fixtures.failing',
                           max_retries=2)

        consumer = Consumer()

        consumer.execute_tasks()
        task.refresh_from_db()
        self.assertEqual(task.status, Task.STATUS_QUEUED)
        self.assertEqual(task.retries, 1)

        consumer.execute_tasks()
        task.refresh_from_db()
        self.assertEqual(task.status, Task.STATUS_QUEUED)
        self.assertEqual(task.retries, 2)

        consumer.execute_tasks()
        task.refresh_from_db()
        self.assertEqual(task.status, Task.STATUS_FAILED)
        self.assertEqual(task.retries, 2)
Example #15
0
def create_background_consumers(count,
                                before_start=None,
                                target='run',
                                *args,
                                **kwargs):
    """Create new Consumer instances on background threads, starts them, and
    return a tuple ([consumer], [thread]).

    :param count: The number of Consumer instances to start.
    :param before_start: A callable that will be called with each consumer as
    an argument before the threads are started.
    :param target: The name of the method of the Consumer that will be run.

    The remaining arguments of the function are passed to the __init__() method
    of each Consumer.
    """

    consumers = []
    threads = []
    for _ in range(count):
        consumer = Consumer(*args, **kwargs)
        consumers.append(consumer)

        thread_target = partial(_consumer_run_and_close_connection, consumer,
                                target)
        thread = threading.Thread(target=thread_target)
        threads.append(thread)

    if before_start:
        for consumer in consumers:
            before_start(consumer)

    for thread in threads:
        thread.start()

    return (consumers, threads)
Example #16
0
 def test_can_import_existing_task(self):
     """Consumer can import a valid and existing @taskified function."""
     consumer = Consumer()
     func = consumer.import_taskified_function('tests.fixtures.do_nothing')
     self.assertIsNotNone(func)
Example #17
0
 def handle(self, *args, **options):
     consumer = Consumer()
     consumer.run()
Example #18
0
 def test_fails_import_non_existing_function(self):
     """Consumer raises when trying to import a non-existing function."""
     consumer = Consumer()
     self.assertRaises(TaskLoadingError, consumer.import_taskified_function,
                       'tests.fixtures.not_a_known_function')