def test_wait_for_job_should_respond_with_queue_and_job_when_a_queue_is_not_empty(self):
        queue = Queue.get_queue('test')
        worker = Worker('test')
        worker.test_content = None

        class Thread(threading.Thread):
            def run(self):
                worker.update_keys()
                queue, job = worker.wait_for_job()
                worker.test_content = queue, job

        # start listening
        thread = Thread()
        thread.start()
        time.sleep(0.1)

        # no job, nothing received
        self.assertIsNone(worker.test_content)

        # add a job
        job = Job.add_job(queue_name='test', identifier='job:1')
        time.sleep(0.1)

        # info should be received
        self.assertEqual(worker.test_content[0].get_pk(), queue.get_pk())
        self.assertTrue(isinstance(worker.test_content[0], Queue))
        self.assertEqual(worker.test_content[1].get_pk(), job.get_pk())
        self.assertTrue(isinstance(worker.test_content[1], Job))

        # job must no be in the queue anymore
        self.assertNotIn(job.get_pk(), queue.waiting.lmembers())
    def test_a_worker_should_run_only_one_time(self):

        worker = Worker('test', max_loops=2)
        worker.run()

        with self.assertRaises(ImplementationError):
            worker.run()
    def tests_worker_should_handle_many_queues(self):
        queue1 = Queue(name='test', priority=1)
        queue2 = Queue(name='test', priority=2)
        worker = Worker('test')
        worker.update_keys()

        self.assertEqual(worker.keys, [queue2.waiting.key, queue1.waiting.key])
    def test_get_job_method_should_return_a_job_based_on_its_pk(self):
        worker = Worker('test')
        job = Job.add_job(queue_name='test', identifier='job:1')

        # a job...
        test_job = worker.get_job(job.get_pk())
        self.assertTrue(isinstance(test_job, Job))
        self.assertEqual(test_job.get_pk(), job.get_pk())

        # not a job...
        with self.assertRaises(ValueError):
            worker.get_job('foo')
    def test_callback_should_be_called(self):
        result = {}

        def callback(job, queue):
            result['job'] = job.get_pk()
            result['queue'] = queue.get_pk()

        job = Job.add_job(identifier='job:1', queue_name='test')
        queue = Queue.get_queue(name='test')
        worker = Worker(name='test', callback=callback, max_loops=1)
        worker.run()

        self.assertEqual(result, {'job': job.get_pk(), 'queue': queue.get_pk()})
    def test_job_error_method_should_be_called(self):
        class ExceptionWithCode(Exception):
            def __init__(self, message, code):
                super(ExceptionWithCode, self).__init__(message)
                self.message = message
                self.code = code

        def callback(job, queue):
            raise ExceptionWithCode('foobar', 42)

        job1 = Job.add_job(identifier='job:1', queue_name='test')
        queue = Queue.get_queue(name='test')
        worker = Worker(name='test', max_loops=1)  # no callback
        worker.run()

        self.assertEqual(job1.status.hget(), STATUSES.ERROR)
        self.assertIn(job1.get_pk(), queue.errors.lmembers())
        self.assertEqual(len(Error.collection()), 1)
        error = Error.get(identifier='job:1')
        self.assertEqual(error.message.hget(), 'You must implement your own action')
        self.assertEqual(error.code.hget(), None)

        job2 = Job.add_job(identifier='job:2', queue_name='test')
        queue = Queue.get_queue(name='test')
        worker = Worker(name='test', max_loops=1, callback=callback)  # callback with exception
        worker.run()

        self.assertEqual(job2.status.hget(), STATUSES.ERROR)
        self.assertIn(job2.get_pk(), queue.errors.lmembers())
        self.assertEqual(len(Error.collection()), 2)
        error = Error.get(identifier='job:2')
        self.assertEqual(error.message.hget(), 'foobar')
        self.assertEqual(error.code.hget(), '42')
    def test_get_queue_method_should_return_a_queue_based_on_its_waiting_field_key(self):
        worker = Worker('test')
        queue = Queue.get_queue('test')

        # a queue...
        test_queue = worker.get_queue(queue.waiting.key)
        self.assertTrue(isinstance(test_queue, Queue))
        self.assertEqual(test_queue.get_pk(), queue.get_pk())

        # a non_existing_queue
        fake_queue_key = test_queue.waiting.key.replace('1', '2')
        with self.assertRaises(ValueError):
            worker.get_queue(fake_queue_key)

        # not a queue...
        with self.assertRaises(DoesNotExist):
            worker.get_queue('foo')
    def test_blpop_timeout(self):
        class TestWorker(Worker):
            def wait_for_job(self):
                result = super(TestWorker, self).wait_for_job()
                if result is None:
                    # force end to quit quickly
                    self.end_forced = True
                return result

        Queue.get_queue('test')

        # test specific methods
        worker = Worker(name='test', timeout=1)
        worker.update_keys()
        test_value = worker.wait_for_job()
        self.assertIsNone(test_value)

        # test whole run
        worker = TestWorker(name='test', timeout=1)
        worker.run()
        self.assertEqual(worker.num_loops, 0)
 def test_worker_without_queues_should_stop(self):
     worker = Worker(name='test', max_loops=1)
     worker.run()
     self.assertEqual(worker.num_loops, 0)
 def test_must_stop_method_should_work(self):
     worker = Worker('test')
     self.assertEqual(worker.must_stop(), False)
     worker.num_loops = worker.max_loops
     self.assertEqual(worker.must_stop(), True)
     worker.num_loops = 0
     worker.end_forced = True
     self.assertEqual(worker.must_stop(), True)
     worker.end_forced = False
     worker.end_signal_caught = True
     self.assertEqual(worker.must_stop(), True)
     worker.terminate_gracefuly = False
     self.assertEqual(worker.must_stop(), False)
 def test_worker_should_stop_after_max_loops(self):
     Job.add_job('job:1', 'test')
     worker = Worker('test', max_loops=1)  # one loop to run only one job
     worker.run()
     self.assertEqual(worker.num_loops, 1)
     self.assertEqual(worker.status, 'terminated')