def test_explicit_retry(self): explicit_retry('foo') self.assertFalse('foo' in state) task = test_huey.dequeue() with CaptureLogs() as capture: self.worker(task) self.assertLogs(capture, ['Executing', 'Re-enqueueing']) task = test_huey.dequeue() self.assertEqual(task.retries, 1) self.worker(task) self.assertEqual(state['foo'], 'fixed') self.assertEqual(len(test_huey), 0) self.assertTaskEvents(('started', task), ('retrying', task), ('started', task), ('finished', task)) explicit_retry('bar') task = test_huey.dequeue() self.worker(task) del state['bar'] task = test_huey.dequeue() self.worker(task) del state['bar'] task = test_huey.dequeue() with CaptureLogs() as capture: self.worker(task) self.assertLogs(capture, ['Executing', 'Cannot retry task']) self.assertEqual(len(test_huey), 0)
def test_worker_exception(self): with CaptureLogs() as capture: blow_up() task = test_huey.dequeue() # Nothing happens because the task is not executed. self.assertLogs(capture, []) with CaptureLogs() as capture: self.worker(task) self.assertLogs(capture, ['Executing', 'Unhandled exception in worker']) self.assertTaskEvents(('started', task), ('error', task))
def test_consumer_integration(self): lock = threading.Lock() @self.huey.task() def add_values(a, b): return a + b consumer = Consumer(self.huey, max_delay=0.1, workers=2, worker_type='thread', health_check_interval=0.01) with CaptureLogs() as capture: consumer.start() try: r1 = add_values(1, 2) r2 = add_values(2, 3) r3 = add_values(3, 5) self.assertEqual(r1.get(blocking=True, timeout=3), 3) self.assertEqual(r2.get(blocking=True, timeout=3), 5) self.assertEqual(r3.get(blocking=True, timeout=3), 8) finally: consumer.stop() for _, worker in consumer.worker_threads: worker.join() messages = capture.messages[-4:-1] for message in messages: self.assertTrue(message.startswith('Executing huey.tests.test_')) self.assertTrue(capture.messages[-1].startswith('Shutting down'))
def test_retry_scheduling(self): # this will continually fail retry_task_delay('blampf') cur_time = datetime.datetime.utcnow() task = self.huey.dequeue() with CaptureLogs() as capture: self.worker(task, cur_time) self.assertLogs( capture, ['Executing', 'Unhandled exception', 'Re-enqueueing task']) in_8 = cur_time + datetime.timedelta(seconds=8) tasks_from_sched = self.huey.read_schedule(in_8) self.assertEqual(tasks_from_sched, []) in_11 = cur_time + datetime.timedelta(seconds=11) tasks_from_sched = self.huey.read_schedule(in_11) self.assertEqual(tasks_from_sched, [task]) task = tasks_from_sched[0] self.assertEqual(task.retries, 2) exec_time = task.execute_time self.assertEqual((exec_time - cur_time).seconds, 10) self.assertTaskEvents(('started', task), ('error', task), ('retrying', task), ('scheduled', task))
def test_retries_with_success(self): # this will fail once, then succeed retry_task('blampf', False) self.assertFalse('blampf' in state) task = test_huey.dequeue() with CaptureLogs() as capture: self.worker(task) self.assertLogs(capture, [ 'Executing', 'Unhandled', 'Re-enqueueing']) task = test_huey.dequeue() self.assertEqual(task.retries, 2) self.worker(task) self.assertEqual(state['blampf'], 'fixed') self.assertEqual(len(test_huey), 0) self.assertTaskEvents( ('started', task), ('error-task', task), ('retrying', task), ('started', task), ('finished', task))
def test_retries_and_logging(self): # This will continually fail. retry_task('blampf') for i in reversed(range(4)): task = test_huey.dequeue() self.assertEqual(task.retries, i) with CaptureLogs() as capture: self.worker(task) if i > 0: self.assertLogs(capture, [ 'Executing', 'Unhandled', 'Re-enqueueing']) self.assertTaskEvents( ('started', task), ('error-task', task), ('retrying', task)) else: self.assertLogs(capture, [ 'Executing', 'Unhandled']) self.assertTaskEvents( ('started', task), ('error-task', task)) self.assertEqual(len(test_huey), 0)
def inner(self): consumer = self.create_consumer() with CaptureLogs() as capture: consumer.start() try: return method(self, consumer, capture) finally: consumer.stop() for _, worker in consumer.worker_threads: worker.join()
def test_message_processing(self): worker = self.consumer._create_worker() self.assertEqual(state, {}) with CaptureLogs() as capture: res = modify_state('k', 'v') worker.loop() self.assertLogs(capture, ['Executing %s' % res.task]) self.assertEqual(state, {'k': 'v'}) self.assertEqual(res.get(), 'v') self.assertTaskEvents(('started', res.task), ('finished', res.task))
def test_retry_with_task(self): retry_with_task(1, -2) task = test_huey.dequeue() with CaptureLogs() as capture: self.worker(task) task = test_huey.dequeue() self.worker(task) self.assertEqual(len(test_huey), 0) ret = retry_with_task(1, 1) self.worker(test_huey.dequeue()) self.assertEqual(ret.get(), 2) self.assertEqual(len(test_huey), 0)
def test_threaded_execution(self): consumer = self.create_consumer() r1 = modify_state('k1', 'v1') r2 = modify_state('k2', 'v2') r3 = modify_state('k3', 'v3') with CaptureLogs() as capture: consumer.start() r1.get(blocking=True) r2.get(blocking=True) r3.get(blocking=True) consumer.stop() for worker in consumer.worker_threads: worker.join() self.assertEqual(state, {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'})
def test_dequeue_errors(self): huey = BrokenHuey() consumer = Consumer(huey, max_delay=0.1, workers=2, worker_type='thread') worker = consumer._create_worker() state = {} @huey.task() def modify_broken(k, v): state[k] = v with CaptureLogs() as capture: res = modify_broken('k', 'v') worker.loop() self.assertEqual(capture.messages, ['Error reading from queue']) self.assertEqual(state, {})