From 0b2a2111568f956549a2c01e179952acc321d38a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= <sybren@stuvel.eu> Date: Tue, 31 Jan 2017 18:03:57 +0100 Subject: [PATCH] Server: added TaskManager.api_find_job_enders() function for Francesco --- packages/flamenco/flamenco/tasks/__init__.py | 30 +++++++++++ packages/flamenco/tests/test_task_manager.py | 52 +++++++++++++++++++- 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/packages/flamenco/flamenco/tasks/__init__.py b/packages/flamenco/flamenco/tasks/__init__.py index 4c8333d6..ef5791cb 100644 --- a/packages/flamenco/flamenco/tasks/__init__.py +++ b/packages/flamenco/flamenco/tasks/__init__.py @@ -107,6 +107,36 @@ class TaskManager(object): task.patch({'op': 'set-task-status', 'status': new_status}, api=api) + def api_find_job_enders(self, job_id): + """Returns a list of tasks that could be the last tasks of a job. + + In other words, returns all tasks that are not a parent of other tasks. + + :returns: list of task IDs + :rtype: list + """ + + from flamenco import current_flamenco + + tasks_coll = current_flamenco.db('tasks') + + # Get the distinct set of tasks used as parents. + parent_tasks = tasks_coll.aggregate([ + {'$match': {'job': job_id}}, + {'$project': {'parents': 1}}, + {'$unwind': {'path': '$parents'}}, + {'$group': {'_id': '$parents'}}, + ]) + parent_ids = [t['_id'] for t in parent_tasks] + + # Get all the tasks that do not have such an ID. + tasks = tasks_coll.find({'job': job_id, + '_id': {'$nin': parent_ids}}, + projection={'_id': 1}) + + tids = [t['_id'] for t in tasks] + return tids + def setup_app(app): from . import eve_hooks, patch diff --git a/packages/flamenco/tests/test_task_manager.py b/packages/flamenco/tests/test_task_manager.py index 1e9bc238..2a7570bc 100644 --- a/packages/flamenco/tests/test_task_manager.py +++ b/packages/flamenco/tests/test_task_manager.py @@ -34,7 +34,7 @@ class TaskManagerTest(AbstractFlamencoTest): commands.Sleep(time_in_seconds=3), ], 'sleep-1-13', - ), + ) # Now test the database contents. with self.app.test_request_context(): @@ -57,3 +57,53 @@ class TaskManagerTest(AbstractFlamencoTest): u'time_in_seconds': 3, } }, dbtask['commands'][1]) + + def test_api_find_jobfinal_tasks(self): + from pillar.api.utils.authentication import force_cli_user + from flamenco.job_compilers import commands + + manager, _, _ = self.create_manager_service_account() + + with self.app.test_request_context(): + force_cli_user() + job_doc = self.jmngr.api_create_job( + 'test job', + u'Wörk wørk w°rk.', + 'sleep', { + 'frames': '12-18, 20-22', + 'chunk_size': 7, + 'time_in_seconds': 3, + }, + self.proj_id, + ctd.EXAMPLE_PROJECT_OWNER_ID, + manager['_id'], + ) + job_id = job_doc['_id'] + + # Find the tasks created so far, use them as parents. + tasks = self.flamenco.db('tasks').find({'job': job_id}, + projection={'_id': 1}) + task_ids = [t['_id'] for t in tasks] + + # dependent task that is used as a single parent. + taskid1 = self.tmngr.api_create_task( + job_doc, [commands.Echo(message=u'ẑžƶźz')], 'zzz 1', parents=task_ids, + ) + + # task dependent on multiple tasks that is not used as a parent. + taskid2 = self.tmngr.api_create_task( + job_doc, [commands.Echo(message=u'ẑžƶźz')], 'zzz 2', parents=task_ids, + ) + + # task dependent on a single task that is not used as a parent. + taskid3 = self.tmngr.api_create_task( + job_doc, [commands.Echo(message=u'ẑžƶźz')], 'zzz 3', parents=[taskid1], + ) + + # independent task + taskid4 = self.tmngr.api_create_task( + job_doc, [commands.Echo(message=u'ẑžƶźz')], 'zzz 4', + ) + + job_enders = self.tmngr.api_find_job_enders(job_id) + self.assertEqual({taskid2, taskid3, taskid4}, set(job_enders)) -- GitLab