import datetime import time try: from math import inf except ImportError: # python 2 doesn't have math.inf, but can use float('inf') inf = float('inf') import pytest from galaxy.model.database_heartbeat import DatabaseHeartbeat from galaxy.queue_worker import ( GalaxyQueueWorker, send_control_task, send_local_control_task, ) from galaxy.queues import connection_from_config from galaxy.web_stack import application_stack_instance def bar(app, **kwargs): app.some_var = 'bar' app.tasks_executed.append('echo') return 'bar' control_message_to_task = {'echo': bar} @pytest.fixture() def queue_worker_factory(request, database_app): def app_factory(): app = setup_queue_worker_test(database_app()) request.addfinalizer(app.queue_worker.shutdown) request.addfinalizer(app.database_heartbeat.shutdown) return app return app_factory def setup_queue_worker_test(app): app.some_var = 'foo' app.tasks_executed = [] server_name = f"{app.amqp_type}.{datetime.datetime.now()}" app.config.server_name = server_name app.config.server_names = [server_name] app.config.attach_to_pools = False app.amqp_internal_connection_obj = connection_from_config(app.config) app.application_stack = application_stack_instance(app=app) app.database_heartbeat = DatabaseHeartbeat(application_stack=app.application_stack, heartbeat_interval=10) app.database_heartbeat.start() time.sleep(0.2) app.queue_worker = GalaxyQueueWorker(app=app, task_mapping=control_message_to_task) app.queue_worker.bind_and_start() time.sleep(0.5) return app def test_send_control_task(queue_worker_factory): app = queue_worker_factory() send_control_task(app=app, task='echo') wait_for_var(app, 'some_var', 'bar') assert len(app.tasks_executed) == 1 def test_send_control_task_to_many_listeners(queue_worker_factory): app1 = queue_worker_factory() app2 = queue_worker_factory() app3 = queue_worker_factory() app4 = queue_worker_factory() app5 = queue_worker_factory() send_control_task(app=app1, task='echo') for app in [app1, app2, app3, app4, app5]: wait_for_var(app, 'some_var', 'bar') assert len(app.tasks_executed) == 1 def test_send_control_task_get_result(queue_worker_factory): app = queue_worker_factory() response = send_control_task(app=app, task='echo', get_response=True) assert response == 'bar' assert app.some_var == 'bar' assert len(app.tasks_executed) == 1 def test_send_local_control_task(queue_worker_factory): app = queue_worker_factory() send_local_control_task(app=app, task='echo') wait_for_var(app, 'some_var', 'bar') assert len(app.tasks_executed) == 1 def test_send_local_control_task_with_past_message(queue_worker_factory): app = queue_worker_factory() app.queue_worker.epoch = inf response = send_local_control_task(app=app, task='echo', get_response=True) assert len(app.tasks_executed) == 0 assert response == 'NO_OP' def test_send_local_control_task_with_non_target_listeners(queue_worker_factory): app1 = queue_worker_factory() app2 = queue_worker_factory() assert app2.some_var == 'foo' send_local_control_task(app=app1, task='echo') wait_for_var(app1, 'some_var', 'bar') assert app2.some_var == 'foo' assert len(app1.tasks_executed) == 1 assert len(app2.tasks_executed) == 0 def test_send_control_task_noop_self(queue_worker_factory): app = queue_worker_factory() assert app.some_var == 'foo' response = send_control_task(app=app, task='echo', noop_self=True, get_response=True) assert response == 'NO_OP' assert app.some_var == 'foo' assert len(app.tasks_executed) == 0 def wait_for_var(obj, var, value, tries=10, sleep=0.25): while getattr(obj, var) != value and tries >= 0: tries -= 1 time.sleep(sleep) assert getattr(obj, var) == value