예제 #1
0
    def test_groupresult_save_restore_nested(self):
        """Test if we can save and restore a nested GroupResult"""
        group_id = uuid()
        async_result = AsyncResult(id=uuid())
        nested_results = [AsyncResult(id=uuid()), AsyncResult(id=uuid())]
        nested_group = GroupResult(id=uuid(), results=nested_results)
        group = GroupResult(id=group_id, results=[nested_group, async_result])

        group.save(backend=self.b)

        restored_group = self.b.restore_group(group_id=group_id)

        assert restored_group == group
예제 #2
0
    def test_join_native_with_group_chain_group(self):
        """Test group(chain(group)) case, join_native can be run correctly.
        In group(chain(group)) case, GroupResult has no _cache property, and
        AsyncBackendMixin.iter_native returns a node instead of node._cache,
        this test make sure ResultSet.join_native can process correctly both
        values of AsyncBackendMixin.iter_native returns.
        """
        def _get_meta(tid, result=None, children=None):
            return {
                'status': states.SUCCESS,
                'result': result,
                'children': children,
                'task_id': tid,
            }

        results = [self.app.AsyncResult(t) for t in [1, 2, 3]]
        values = [(_.id, _get_meta(_.id, _)) for _ in results]
        g_res = GroupResult(6, [self.app.AsyncResult(t) for t in [4, 5]])
        results += [g_res]
        values += [(6, g_res.children)]
        x = self.app.ResultSet(results)
        x.results[0].backend = Mock()
        x.results[0].backend.join = Mock()
        x.results[3][0].get = Mock()
        x.results[3][0].get.return_value = g_res.results[0]
        x.results[3][1].get = Mock()
        x.results[3][1].get.return_value = g_res.results[1]
        x.iter_native = Mock()
        x.iter_native.return_value = values.__iter__()
        x.join_native()
        x.iter_native.assert_called()
예제 #3
0
 def test_forget(self):
     subs = [MockAsyncResultSuccess(uuid()),
             MockAsyncResultSuccess(uuid())]
     ts = GroupResult(uuid(), subs)
     ts.forget()
     for sub in subs:
         self.assertTrue(sub.forgotten)
예제 #4
0
 def test_iter_native(self):
     backend = SimpleBackend()
     subtasks = [AsyncResult(uuid(), backend=backend)
                     for i in range(10)]
     ts = GroupResult(uuid(), subtasks)
     backend.ids = [subtask.id for subtask in subtasks]
     self.assertEqual(len(list(ts.iter_native())), 10)
예제 #5
0
 def test_iterate_yields(self):
     ar = MockAsyncResultSuccess(uuid())
     ar2 = MockAsyncResultSuccess(uuid())
     ts = GroupResult(uuid(), [ar, ar2])
     it = iter(ts)
     self.assertEqual(it.next(), 42)
     self.assertEqual(it.next(), 42)
예제 #6
0
 def test_join_native(self):
     backend = SimpleBackend()
     subtasks = [AsyncResult(uuid(), backend=backend) for i in range(10)]
     ts = GroupResult(uuid(), subtasks)
     backend.ids = [subtask.id for subtask in subtasks]
     res = ts.join_native()
     self.assertEqual(res, range(10))
예제 #7
0
 def test_join_timeout(self):
     ar = MockAsyncResultSuccess(uuid())
     ar2 = MockAsyncResultSuccess(uuid())
     ar3 = AsyncResult(uuid())
     ts = GroupResult(uuid(), [ar, ar2, ar3])
     with self.assertRaises(TimeoutError):
         ts.join(timeout=0.0000001)
예제 #8
0
 def test_iterate_eager(self):
     ar1 = EagerResult(uuid(), 42, states.SUCCESS)
     ar2 = EagerResult(uuid(), 42, states.SUCCESS)
     ts = GroupResult(uuid(), [ar1, ar2])
     it = iter(ts)
     self.assertEqual(it.next(), 42)
     self.assertEqual(it.next(), 42)
예제 #9
0
 def setup(self):
     self.size = 11
     subtasks = make_mock_group(10)
     failed = mock_task('ts11', states.FAILURE, KeyError('Baz'))
     save_result(failed)
     failed_res = AsyncResult(failed['id'])
     self.ts = GroupResult(uuid(), subtasks + [failed_res])
예제 #10
0
파일: test.py 프로젝트: hysds/sciflo
def join_map_jobs(task_ids):
    """Test reduce function that manually joins all mapped jobs."""

    print(("task_ids: {}".format(json.dumps(task_ids, indent=2))))
    res = GroupResult(id=uuid.uuid4().bytes, results=[
                      AsyncResult(id[0]) for id in task_ids])
    while True:
        ready = res.ready()
        if ready:
            break
        time.sleep(5)
    results = []
    for r in res.join(timeout=10.):
        # deduped job?
        if isinstance(r, (list, tuple)):
            # build resolvable result
            task_id = r[0]
            results.append({'uuid': task_id,
                            'job_id': task_id,
                            'payload_id': task_id,
                            'status': 'job-deduped'})
        else:
            results.append(r)
    args = [result['payload_id'] for result in results]
    return args
    def test_on_chord_part_return(self):
        """Test if the ChordCounter is properly decremented and the callback is
        triggered after all chord parts have returned"""
        gid = uuid()
        tid1 = uuid()
        tid2 = uuid()
        subtasks = [AsyncResult(tid1), AsyncResult(tid2)]
        group = GroupResult(id=gid, results=subtasks)
        self.b.apply_chord(group, self.add.s())

        chord_counter = ChordCounter.objects.get(group_id=gid)
        assert chord_counter.count == 2

        request = mock.MagicMock()
        request.id = subtasks[0].id
        request.group = gid
        request.task = "my_task"
        request.args = ["a", 1, "password"]
        request.kwargs = {"c": 3, "d": "e", "password": "******"}
        request.argsrepr = "argsrepr"
        request.kwargsrepr = "kwargsrepr"
        request.hostname = "celery@ip-0-0-0-0"
        result = {"foo": "baz"}

        self.b.mark_as_done(tid1, result, request=request)

        chord_counter.refresh_from_db()
        assert chord_counter.count == 1

        self.b.mark_as_done(tid2, result, request=request)

        with pytest.raises(ChordCounter.DoesNotExist):
            ChordCounter.objects.get(group_id=gid)

        request.chord.delay.assert_called_once()
예제 #12
0
 def test_save_restore_delete_group(self):
     tid = uuid()
     tsr = GroupResult(tid, [AsyncResult(uuid()) for _ in range(10)])
     self.b.save_group(tid, tsr)
     self.b.restore_group(tid)
     self.assertEqual(self.b.restore_group(tid), tsr)
     self.b.delete_group(tid)
     self.assertIsNone(self.b.restore_group(tid))
예제 #13
0
 def test_save_restore(self):
     subs = [MockAsyncResultSuccess(uuid()), MockAsyncResultSuccess(uuid())]
     ts = GroupResult(uuid(), subs)
     ts.save()
     with self.assertRaises(AttributeError):
         ts.save(backend=object())
     self.assertEqual(GroupResult.restore(ts.id).subtasks, ts.subtasks)
     ts.delete()
     self.assertIsNone(GroupResult.restore(ts.id))
예제 #14
0
    def test_groupresult_save_restore(self):
        """Test if we can save and restore a GroupResult"""
        group_id = uuid()
        results = [AsyncResult(id=uuid())]
        group = GroupResult(id=group_id, results=results)

        group.save(backend=self.b)

        restored_group = self.b.restore_group(group_id=group_id)

        assert restored_group == group
예제 #15
0
 def test_apply_chord_header_result_arg(self):
     """Test if apply_chord can handle Celery <= 5.1 call signature"""
     gid = uuid()
     tid1 = uuid()
     tid2 = uuid()
     subtasks = [AsyncResult(tid1), AsyncResult(tid2)]
     group = GroupResult(id=gid, results=subtasks)
     # Celery < 5.1
     self.b.apply_chord(group, self.add.s())
     # Celery 5.1
     self.b.apply_chord((uuid(), subtasks), self.add.s())
예제 #16
0
def cancel(request, instance, import_type, import_event_id):
    ie = _get_import_event(instance, import_type, import_event_id)

    ie.status = GenericImportEvent.CANCELED
    ie.save()

    # If verifications tasks are still scheduled, we need to revoke them
    if ie.task_id:
        GroupResult(ie.task_id).revoke()

    return list_imports(request, instance)
예제 #17
0
 def _freeze(self, _id=None):
     opts = self.options
     try:
         gid = opts['group']
     except KeyError:
         gid = opts['group'] = uuid()
     new_tasks, results = [], []
     for task in self.tasks:
         task = maybe_subtask(task).clone()
         results.append(task._freeze())
         new_tasks.append(task)
     self.tasks = self.kwargs['tasks'] = new_tasks
     return GroupResult(gid, results)
예제 #18
0
    def group_result(self, app=None):
        """Return the GroupResult of self.

        Arguments:
        ---------
            app (Celery): app instance to create the GroupResult with.

        """
        return GroupResult(
            self.group_id,
            [result_from_tuple(r, app=app)
             for r in json.loads(self.sub_tasks)],
            app=app,
        )
 def post(self):
     task_ids = request.form.getlist('task_ids')
     results = [AsyncResult(tid, app=app.celery) for tid in task_ids]
     group_result = GroupResult(id=str(uuid.uuid4()), results=results)
     group_result.save()
     successful = all_finished(group_result.results)
     return {
         'status':
         'SUCCESS' if successful else 'PENDING',
         'bulk_task_id':
         str(group_result.id),
         'bulk_task_url':
         app.api.url_for(TaskSubscriptionAPI,
                         bulk_task_id=str(group_result.id),
                         _external=True),
         'task_results':
         get_all_task_results(group_result.results)
     }
    def test_callback_failure(self):
        """Test if a failure in the chord callback is properly handled"""
        gid = uuid()
        tid1 = uuid()
        tid2 = uuid()
        cid = uuid()
        subtasks = [AsyncResult(tid1), AsyncResult(tid2)]
        group = GroupResult(id=gid, results=subtasks)
        self.b.apply_chord(group, self.add.s())

        chord_counter = ChordCounter.objects.get(group_id=gid)
        assert chord_counter.count == 2

        request = mock.MagicMock()
        request.id = subtasks[0].id
        request.group = gid
        request.task = "my_task"
        request.args = ["a", 1, "password"]
        request.kwargs = {"c": 3, "d": "e", "password": "******"}
        request.argsrepr = "argsrepr"
        request.kwargsrepr = "kwargsrepr"
        request.hostname = "celery@ip-0-0-0-0"
        request.properties = {"periodic_task_name": "my_periodic_task"}
        request.ignore_result = False
        request.chord.id = cid
        result = {"foo": "baz"}

        # Trigger an exception when the callback is triggered
        request.chord.delay.side_effect = ValueError()

        self.b.mark_as_done(tid1, result, request=request)

        chord_counter.refresh_from_db()
        assert chord_counter.count == 1

        self.b.mark_as_done(tid2, result, request=request)

        with pytest.raises(ChordCounter.DoesNotExist):
            ChordCounter.objects.get(group_id=gid)

        request.chord.delay.assert_called_once()

        assert TaskResult.objects.get(task_id=cid).status == states.FAILURE
예제 #21
0
    def stop_jobs(jobs: List[Job], job_options: Dict[str, Any]):
        raise NotImplementedError
        # TODO: not sure whether we should .revoke(terminate=True)
        # TODO: one of the options below should work, but I don't have time to test it right now...

        # http://docs.celeryproject.org/en/latest/userguide/workers.html#worker-persistent-revokes
        from celery.result import AsyncResult
        AsyncResult(job_options['command_id']).revoke()

        # https://docs.celeryproject.org/en/stable/reference/celery.result.html
        from celery.result import GroupResult
        g = GroupResult(id=job_options['command_id'])

        # https://stackoverflow.com/questions/13685344/retrieving-groupresult-from-taskset-id-in-celery
        # We may need to call result.save() in the task above for it to work...
        from celery.result import GroupResult
        result = GroupResult.restore(job_options['command_id'])
        result.revoke()

        from celery.task.control import revoke
        revoke(job_options['command_id'])
    def test_on_chord_part_return_failure(self):
        """Test if a failure in one of the chord header tasks is properly handled
        and the callback was not triggered
        """
        gid = uuid()
        tid1 = uuid()
        tid2 = uuid()
        cid = uuid()
        subtasks = [AsyncResult(tid1), AsyncResult(tid2)]
        group = GroupResult(id=gid, results=subtasks)
        self.b.apply_chord(group, self.add.s())

        chord_counter = ChordCounter.objects.get(group_id=gid)
        assert chord_counter.count == 2

        request = mock.MagicMock()
        request.id = tid1
        request.group = gid
        request.task = "my_task"
        request.args = ["a", 1, "password"]
        request.kwargs = {"c": 3, "d": "e", "password": "******"}
        request.argsrepr = "argsrepr"
        request.kwargsrepr = "kwargsrepr"
        request.hostname = "celery@ip-0-0-0-0"
        request.properties = {"periodic_task_name": "my_periodic_task"}
        request.chord.id = cid
        result = {"foo": "baz"}

        self.b.mark_as_done(tid1, result, request=request)

        chord_counter.refresh_from_db()
        assert chord_counter.count == 1

        request.id = tid2
        self.b.mark_as_failure(tid2, ValueError(), request=request)

        with pytest.raises(ChordCounter.DoesNotExist):
            ChordCounter.objects.get(group_id=gid)

        request.chord.delay.assert_not_called()
예제 #23
0
 def test_GroupResult(self):
     x = GroupResult(uuid(), [AsyncResult(uuid()) for _ in range(10)])
     self.assertEqual(x, from_serializable(x.serializable()))
     self.assertEqual(x, from_serializable(x))
예제 #24
0
 def setup(self):
     self.ts = GroupResult(
         uuid(),
         [AsyncResult(uuid()), AsyncResult(uuid())])
예제 #25
0
def group_status(group_id, result_ids):
    results = [AsyncResult(r_id) for r_id in result_ids]
    gr = GroupResult(id, results)

    return gr.successful()
예제 #26
0
class test_RedisBackend_chords_complex(basetest_RedisBackend):
    @pytest.fixture(scope="function", autouse=True)
    def complex_header_result(self):
        with patch("celery.result.GroupResult.restore") as p:
            yield p

    @pytest.mark.parametrize(['results', 'assert_save_called'], [
        # No results in the header at all - won't call `save()`
        (tuple(), False),
        # Simple results in the header - won't call `save()`
        ((AsyncResult("foo"), ), False),
        # Many simple results in the header - won't call `save()`
        ((AsyncResult("foo"), ) * 42, False),
        # A single complex result in the header - will call `save()`
        ((GroupResult("foo", []),), True),
        # Many complex results in the header - will call `save()`
        ((GroupResult("foo"), ) * 42, True),
        # Mixed simple and complex results in the header - will call `save()`
        (itertools.islice(
            itertools.cycle((
                AsyncResult("foo"), GroupResult("foo"),
            )), 42,
        ), True),
    ])
    def test_apply_chord_complex_header(self, results, assert_save_called):
        mock_group_result = Mock()
        mock_group_result.return_value.results = results
        self.app.GroupResult = mock_group_result
        header_result_args = ("gid11", results)
        self.b.apply_chord(header_result_args, None)
        if assert_save_called:
            mock_group_result.return_value.save.assert_called_once_with(backend=self.b)
        else:
            mock_group_result.return_value.save.assert_not_called()

    def test_on_chord_part_return_timeout(self, complex_header_result):
        tasks = [self.create_task(i) for i in range(10)]
        random.shuffle(tasks)
        try:
            self.app.conf.result_chord_join_timeout += 1.0
            for task, result_val in zip(tasks, itertools.cycle((42, ))):
                self.b.on_chord_part_return(
                    task.request, states.SUCCESS, result_val,
                )
        finally:
            self.app.conf.result_chord_join_timeout -= 1.0

        join_func = complex_header_result.return_value.join_native
        join_func.assert_called_once_with(timeout=4.0, propagate=True)

    @pytest.mark.parametrize("supports_native_join", (True, False))
    def test_on_chord_part_return(
        self, complex_header_result, supports_native_join,
    ):
        mock_result_obj = complex_header_result.return_value
        mock_result_obj.supports_native_join = supports_native_join

        tasks = [self.create_task(i) for i in range(10)]
        random.shuffle(tasks)

        with self.chord_context(10) as (tasks, request, callback):
            for task, result_val in zip(tasks, itertools.cycle((42, ))):
                self.b.on_chord_part_return(
                    task.request, states.SUCCESS, result_val,
                )
                # Confirm that `zadd` was called even though we won't end up
                # using the data pushed into the sorted set
                assert self.b.client.zadd.call_count == 1
                self.b.client.zadd.reset_mock()
        # Confirm that neither `zrange` not `lrange` were called
        self.b.client.zrange.assert_not_called()
        self.b.client.lrange.assert_not_called()
        # Confirm that the `GroupResult.restore` mock was called
        complex_header_result.assert_called_once_with(request.group)
        # Confirm the the callback was called with the `join()`ed group result
        if supports_native_join:
            expected_join = mock_result_obj.join_native
        else:
            expected_join = mock_result_obj.join
        callback.delay.assert_called_once_with(expected_join())
예제 #27
0
 def test_getitem(self):
     subs = [MockAsyncResultSuccess(uuid()), MockAsyncResultSuccess(uuid())]
     ts = GroupResult(uuid(), subs)
     self.assertIs(ts[0], subs[0])
예제 #28
0
 def test_iterate_raises(self):
     ar = MockAsyncResultFailure(uuid())
     ts = GroupResult(uuid(), [ar])
     it = iter(ts)
     with self.assertRaises(KeyError):
         it.next()
예제 #29
0
 def setup(self):
     self.size = 10
     self.ts = GroupResult(uuid(), make_mock_group(self.size))
예제 #30
0
파일: workUnit.py 프로젝트: hysds/sciflo
    def _run(self):
        """Submit the parallel work jobs, wait for all to complete, and return the results."""

        # get map and work functions
        workFunc = getFunction(self._call)

        # get list of jobs
        jobs = []
        if not isinstance(self._args[0], (list, tuple)):
            raise ParMapWorkUnitError(
                "Invalid type for ParWorkUnit argument 1: %s\n%s" %
                (type(self._args[0]), self._args[0]))

        for i, arg in enumerate(self._args[0]):
            workArgs = [arg]
            for mapArg in self._args[1:]:
                if isinstance(mapArg, (list, tuple)) and len(mapArg) == len(
                        self._args[0]):
                    workArgs.append(mapArg[i])
                else:
                    workArgs.append(mapArg)

            # append work unit id and job number for job tracking
            job = workFunc(*workArgs, **{'wuid': self._wuid, 'job_num': i})

            # update context in job payload
            job.setdefault('context', {}).update(self._ctx)

            # propagate job/container configs from HySDS context
            if 'priority' not in job:
                job['priority'] = int(self._ctx.get('job_priority', 0))
            if 'username' not in job:
                job['username'] = self._ctx.get('username', None)
            if 'container_image_name' not in job:
                job['container_image_name'] = self._ctx.get(
                    'container_image_name', None)
            if 'container_image_url' not in job:
                job['container_image_url'] = self._ctx.get(
                    'container_image_url', None)
            if 'container_mappings' not in job:
                job['container_mappings'] = self._ctx.get(
                    'container_mappings', {})

            # set tag from HySDS context
            if 'tag' not in job and 'tag' in self._ctx:
                job['tag'] = self._ctx['tag']

            jobs.append(job)

        # submit jobs and wait for execution
        group_res = group(
            submit_job.s(job).set(queue=self._job_queue) for job in jobs)()
        while True:
            ready = group_res.ready()
            if ready:
                break
            time.sleep(5)
        task_ids = group_res.join(timeout=10.)

        # if async, return task IDs; otherwise harvest results in a group then return
        if self._async:
            return [id for id in task_ids]
        else:
            res = GroupResult(id=uuid.uuid4().bytes,
                              results=[AsyncResult(id[0]) for id in task_ids])
            while True:
                ready = res.ready()
                if ready:
                    break
                time.sleep(5)
            results = []
            for r in res.join(timeout=10.):
                # deduped job?
                if isinstance(r, (list, tuple)):
                    # build resolvable result
                    task_id = r[0]
                    results.append({
                        'uuid': task_id,
                        'job_id': task_id,
                        'payload_id': task_id,
                        'status': 'job-deduped'
                    })
                else:
                    results.append(r)
            return results