def wrapper(*args, **kwargs): if kwargs.get('check_workers', True): try: if not workers(): return ActionResult(result=False, message='can not find celery workers, please check worker status') except exceptions.RabbitMQConnectionError as e: return ActionResult(result=False, message='celery worker status check failed with message: %s, ' 'check rabbitmq status please' % e.message) except RedisConnectionError: return ActionResult(result=False, message='redis connection error, check redis status please') return func(*args, **kwargs)
def start(self, executor, check_workers=True): """ 启动当前流程 @param executor: 执行者 @param check_workers: 是否检测 worker 的状态 @return: 执行结果 """ from pipeline.engine import api from pipeline.utils.context import get_pipeline_context from pipeline.engine.models import FunctionSwitch from pipeline.engine.core.api import workers if FunctionSwitch.objects.is_frozen(): return ActionResult(result=False, message='engine has been freeze, try later please') if check_workers: try: if not workers(): return ActionResult(result=False, message='can not find celery workers, please check worker status') except RabbitMQConnectionError as e: return ActionResult(result=False, message='celery worker status check failed with message: %s, ' 'check rabbitmq status please' % e.message) except RedisConnectionError: return ActionResult(result=False, message='redis connection error, check redis status please') with transaction.atomic(): instance = self.__class__.objects.select_for_update().get(id=self.id) if instance.is_started: return ActionResult(result=False, message='pipeline instance already started.') instance.start_time = timezone.now() instance.is_started = True instance.executor = executor # calculate tree info instance.calculate_tree_info() pipeline_data = instance.execution_data try: parser_cls = import_string(settings.PIPELINE_PARSER_CLASS) except ImportError: return ActionResult(result=False, message='invalid parser class: %s' % settings.PIPELINE_PARSER_CLASS) parser = parser_cls(pipeline_data) pipeline = parser.parse(get_pipeline_context(instance, 'instance')) instance.save() return api.start_pipeline(pipeline, check_workers=check_workers)
def test_workers(self): # throw error def throw_conn_error(*args, **kwargs): raise ConnectionError() with mock.patch('pipeline.engine.core.data.cache_for', throw_conn_error): self.assertRaises(ConnectionError, api.workers) # cache situation def return_worker_list(*args, **kwargs): return ['worker-1', 'worker-2'] with mock.patch('pipeline.engine.core.data.cache_for', return_worker_list): worker = api.workers() self.assertEqual(worker, return_worker_list()) current_app.control.ping.assert_not_called() data.expire_cache.assert_not_called() # no cache def return_none(*args, **kwargs): return None with mock.patch('pipeline.engine.core.data.cache_for', return_none): # no workers def no_workers(*args, **kwargs): return [] current_app.control.ping.reset_mock() data.expire_cache.reset_mock() with mock.patch('djcelery.app.current_app.control.ping', no_workers): worker = api.workers() self.assertEqual(worker, no_workers()) data.expire_cache.assert_not_called() # has workers def two_workers(*args, **kwargs): return ['w1', 'w2'] current_app.control.ping.reset_mock() data.expire_cache.reset_mock() with mock.patch('djcelery.app.current_app.control.ping', two_workers): worker = api.workers() self.assertEqual(worker, two_workers()) data.expire_cache.assert_called_with('__pipeline__workers__', two_workers(), settings.PIPELINE_WORKER_STATUS_CACHE_EXPIRES) # raise exception def raise_mq_conn_error(*args, **kwargs): raise socket.error() current_app.control.ping.reset_mock() data.expire_cache.reset_mock() with mock.patch('djcelery.app.current_app.control.ping', raise_mq_conn_error): self.assertRaises(RabbitMQConnectionError, api.workers) data.expire_cache.assert_not_called() # retry test ping_mock = mock.MagicMock(side_effect=[[], two_workers()]) with mock.patch('djcelery.app.current_app.control.ping', ping_mock): worker = api.workers() self.assertEqual(worker, two_workers()) ping_mock.assert_has_calls([ mock.call(timeout=1), mock.call(timeout=2) ]) data.expire_cache.assert_called_with('__pipeline__workers__', two_workers(), settings.PIPELINE_WORKER_STATUS_CACHE_EXPIRES)