def test_update_process(self): workflow = Workflow.objects.create(name='one') node = Node.objects.create(name='one', workflow=workflow, is_start=True, is_end=True, celery_task=dummy, role=self.bosses) process = Process.objects.create(workflow=workflow) task = Task.objects.create(node=node, process=process, user=self.boss) subprocess = Process.objects.create(workflow=workflow, parent=task) subtask = Task.objects.create(node=node, process=subprocess, user=self.boss) process = shortcuts.update_process(process.pk, state='STARTED') self.assertEquals(process.state, 'STARTED') shortcuts.update_task(subtask.pk, result='1') shortcuts.update_process(subprocess.pk, state='SUCCESS') task = shortcuts.update_task(task.pk) self.assertEquals(task.state, 'SUCCESS') self.assertEquals(task.result, '1')
def test_is_launchable(self): """ node1 ----- |-- join_node node2------ """ workflow = Workflow.objects.create(name='main') process = Process.objects.create(workflow=workflow) join_node = Node.objects.create(name='join', workflow=workflow, join='XOR', celery_task=dummy, role=self.bosses) node1 = Node.objects.create(name='one', workflow=workflow, celery_task=dummy, role=self.bosses) node2 = Node.objects.create(name='two', workflow=workflow, celery_task=dummy, role=self.bosses) # With no parent transitions, it must be always launchable self.assertTrue(shortcuts.is_launchable(join_node, process)) task1 = Task.objects.create(node=node1, process=process, user=self.boss) task2 = Task.objects.create(node=node2, process=process, user=self.boss) Transition.objects.create(workflow=workflow, parent=node1, child=join_node) Transition.objects.create(workflow=workflow, parent=node2, child=join_node) # With parent transitions but without fulfilled tasks, it's not launchable self.assertFalse(shortcuts.is_launchable(join_node, process)) # With a XOR join and with one fulfilled task, it's launchable shortcuts.update_task(task1.pk, state='SUCCESS') self.assertTrue(shortcuts.is_launchable(join_node, process)) # With an AND join and with one fulfilled task, it's not launchable join_node.join = 'AND' join_node.save() self.assertFalse(shortcuts.is_launchable(join_node, process)) # With an AND join and with all tasks fulfilled, it's launchable shortcuts.update_task(task2.pk, state='SUCCESS') self.assertTrue(shortcuts.is_launchable(join_node, process))
def test_get_pending_childs(self): """ |-- child1 parent --| |-- child2 """ workflow = Workflow.objects.create(name='main') process = Process.objects.create(workflow=workflow) parent = Node.objects.create(name='parent', workflow=workflow, celery_task=dummy, role=self.bosses) parent_task = Task.objects.create(node=parent, process=process, user=self.boss) child1 = Node.objects.create(name='one', workflow=workflow, celery_task=dummy, role=self.bosses) child2 = Node.objects.create(name='two', workflow=workflow, celery_task=dummy, role=self.bosses) Transition.objects.create(workflow=workflow, parent=parent, child=child1) Transition.objects.create(workflow=workflow, parent=parent, child=child2) # If the parent is not successful, no child is returned self.assertEqual(len(shortcuts.get_pending_childs(parent_task)), 0) shortcuts.update_task(parent_task.pk, state='SUCCESS') # If a parent is successful and had a XOR split, one child is returned parent.split = 'XOR' parent.save() self.assertEqual(len(shortcuts.get_pending_childs(parent_task)), 1) # If a parent is successful and had an AND split, all childs are returned parent.split = 'AND' parent.save() self.assertEqual(len(shortcuts.get_pending_childs(parent_task)), 2)
def test_update_task(self): workflow = Workflow.objects.create(name='one') process = Process.objects.create(workflow=workflow) node = Node.objects.create(name='one', workflow=workflow, celery_task=dummy, role=self.bosses) task = Task.objects.create(node=node, process=process, user=self.boss) task = shortcuts.update_task(task.pk, task_id='example', result='2') self.assertEquals(task.task_id, 'example') self.assertEquals(task.result, '2')
def test_is_launchable(self): """ node1 ----- |-- join_node node2------ """ workflow = Workflow.objects.create(name='main') process = Process.objects.create(workflow=workflow) join_node = Node.objects.create(name='join', workflow=workflow, join='XOR', celery_task=dummy, role=self.bosses) node1 = Node.objects.create(name='one', workflow=workflow, celery_task=dummy, role=self.bosses) node2 = Node.objects.create(name='two', workflow=workflow, celery_task=dummy, role=self.bosses) # With no parent transitions, it must be always launchable self.assertTrue(shortcuts.is_launchable(join_node, process)) task1 = Task.objects.create(node=node1, process=process, user=self.boss) task2 = Task.objects.create(node=node2, process=process, user=self.boss) Transition.objects.create(workflow=workflow, parent=node1, child=join_node) Transition.objects.create(workflow=workflow, parent=node2, child=join_node) # With parent transitions but without fulfilled tasks, it's not launchable self.assertFalse(shortcuts.is_launchable(join_node, process)) # With a XOR join and with one fulfilled task, it's launchable shortcuts.update_task(task1.pk, state='SUCCESS') self.assertTrue(shortcuts.is_launchable(join_node, process)) # With an AND join and with one fulfilled task, it's not launchable join_node.join = 'AND'; join_node.save() self.assertFalse(shortcuts.is_launchable(join_node, process)) # With an AND join and with all tasks fulfilled, it's launchable shortcuts.update_task(task2.pk, state='SUCCESS') self.assertTrue(shortcuts.is_launchable(join_node, process))
def task_revoked(pk): """Stop the task, mark it as revoked and execute BPM logic: - if the task executed a subprocess, revoke the process """ task = update_task(pk=pk, state="REVOKED", end_date=now()) result = AbortableAsyncResult(task.task_id) result.abort() revoke(task.task_id, terminate=True) for subprocess in task.subprocesses.iterator(): subprocess.stop() subprocess.update(state="REVOKED", end_date=task.end_date) logger.info('Subprocess "{subprocess}" revoked by task ' '"{task}"'.format(subprocess=subprocess, task=task))
def task_started(pk, task_id): """Mark the task as started and execute BPM logic: - if it's the beginning of a process, mark the process as started - if there is no need of them, cancel the running ancestors """ task = update_task(pk=pk, task_id=task_id, state="STARTED", start_date=now()) if task.node.is_start: task.process.update(state="STARTED", start_date=task.start_date) logger.info('Process "{}" started'.format(task.process)) for parent in task.get_revocable_parents(): parent.revoke() logger.info('Parent task "{}" is not longer needed for task "{}"'.format(parent, task))
def test_get_pending_childs(self): """ |-- child1 parent --| |-- child2 """ workflow = Workflow.objects.create(name='main') process = Process.objects.create(workflow=workflow) parent = Node.objects.create(name='parent', workflow=workflow, celery_task=dummy, role=self.bosses) parent_task = Task.objects.create(node=parent, process=process, user=self.boss) child1 = Node.objects.create(name='one', workflow=workflow, celery_task=dummy, role=self.bosses) child2 = Node.objects.create(name='two', workflow=workflow, celery_task=dummy, role=self.bosses) Transition.objects.create(workflow=workflow, parent=parent, child=child1) Transition.objects.create(workflow=workflow, parent=parent, child=child2) # If the parent is not successful, no child is returned self.assertEqual(len(shortcuts.get_pending_childs(parent_task)), 0) shortcuts.update_task(parent_task.pk, state='SUCCESS') # If a parent is successful and had a XOR split, one child is returned parent.split = 'XOR'; parent.save() self.assertEqual(len(shortcuts.get_pending_childs(parent_task)), 1) # If a parent is successful and had an AND split, all childs are returned parent.split = 'AND'; parent.save() self.assertEqual(len(shortcuts.get_pending_childs(parent_task)), 2)
def task_revoked(pk): """Stop the task, mark it as revoked and execute BPM logic: - if the task executed a subprocess, revoke the process """ task = update_task(pk=pk, state='REVOKED', end_date=now()) result = AbortableAsyncResult(task.task_id) result.abort() revoke(task.task_id, terminate=True) for subprocess in task.subprocesses.iterator(): subprocess.stop() subprocess.update(state='REVOKED', end_date=task.end_date) logger.info('Subprocess "{subprocess}" revoked by task ' '"{task}"'.format(subprocess=subprocess, task=task))
def task_succeeded(pk, result): """Mark the task as succeeded and execute BPM logic: - if it's the ending of a process, mark the process as suceeded - launch the needed children """ task = update_task(pk=pk, state="SUCCESS", result=result, progress=100, end_date=now()) if task.node.is_end: task.process.update(state="SUCCESS", end_date=task.end_date) logger.info('Process "{}" succeeded'.format(task.process)) else: for child in task.get_pending_childs(): task.process.launch_node(child) logger.info('Node "{child}" launched by task "{task}"'.format(child=child, task=task))
def task_failed(pk): """Mark the task as failed and execute BPM logic: - if it's the ending of a process, mark the process as failed - if there's an alternative way to continue the workflow, execute the alternative tasks """ task = update_task(pk=pk, state='FAILED', end_date=now()) if task.node.is_end: task.process.update(state='FAILED', end_date=task.end_date) logger.info('Process "{process}" failed'.format(process=task.process)) task.get_alternative_way() if alternative: task.process.launch_node(alternative) logger.info('Alternative node "{alternative}" launched by task ' '"{task}"'.format(alternative=alternative, task=task))
def task_failed(pk): """Mark the task as failed and execute BPM logic: - if it's the ending of a process, mark the process as failed - if there's an alternative way to continue the workflow, execute the alternative tasks """ task = update_task(pk=pk, state="FAILED", end_date=now()) if task.node.is_end: task.process.update(state="FAILED", end_date=task.end_date) logger.info('Process "{process}" failed'.format(process=task.process)) task.get_alternative_way() if alternative: task.process.launch_node(alternative) logger.info( 'Alternative node "{alternative}" launched by task ' '"{task}"'.format(alternative=alternative, task=task) )
def task_started(pk, task_id): """Mark the task as started and execute BPM logic: - if it's the beginning of a process, mark the process as started - if there is no need of them, cancel the running ancestors """ task = update_task(pk=pk, task_id=task_id, state='STARTED', start_date=now()) if task.node.is_start: task.process.update(state='STARTED', start_date=task.start_date) logger.info('Process "{}" started'.format(task.process)) for parent in task.get_revocable_parents(): parent.revoke() logger.info( 'Parent task "{}" is not longer needed for task "{}"'.format( parent, task))
def task_succeeded(pk, result): """Mark the task as succeeded and execute BPM logic: - if it's the ending of a process, mark the process as suceeded - launch the needed children """ task = update_task(pk=pk, state='SUCCESS', result=result, progress=100, end_date=now()) if task.node.is_end: task.process.update(state='SUCCESS', end_date=task.end_date) logger.info('Process "{}" succeeded'.format(task.process)) else: for child in task.get_pending_childs(): task.process.launch_node(child) logger.info('Node "{child}" launched by task "{task}"'.format( child=child, task=task))
def task_progress(pk, progress): """Update the tasks progress.""" update_task(pk=pk, progress=progress)
def task_retried(pk): """Mark the task as retried.""" update_task(pk, state='RETRIED')
def update(self, **kwargs): return update_task(pk=self.pk, **kwargs)
def task_retried(pk): """Mark the task as retried.""" update_task(pk, state="RETRIED")