Ejemplo n.º 1
0
    def save(self, *args, **kwargs):
        if self.status == Task.STATUS.PREPARED:
            raise FlowRuntimeError(
                "Can't save task with intermediate status - PREPARED")

        if self.flow_task:
            self.flow_task_type = self.flow_task.task_type

        super(Task, self).save(*args, **kwargs)
Ejemplo n.º 2
0
    def prepare(self, data=None):
        super(TaskViewActivation, self).prepare()

        management_form_cls = self.get_management_form_cls()
        self.management_form = management_form_cls(data=data, instance=self.task)

        if data:
            if not self.management_form.is_valid():
                raise FlowRuntimeError('Activation metadata is broken {}'.format(self.management_form.errors))
            self.task = self.management_form.save(commit=False)
Ejemplo n.º 3
0
    def execute(self):
        for node, cond in self.flow_task.branches:
            if cond:
                if cond(self.process):
                    self.next_tasks.append(node)
            else:
                self.next_tasks.append(node)

        if not self.next_tasks:
            raise FlowRuntimeError('No next task available for {}'.format(
                self.flow_task.name))
Ejemplo n.º 4
0
 def activate_next(self):
     if self._approvers:
         token_source = Token.split_token_source(self.task.token,
                                                 self.task.pk)
         for user in self._approvers:
             next_task = self.flow_task._next.activate(
                 prev_activation=self, token=next(token_source))
             next_task.assign(user)
             self.update_approve_task(next_task.task)
     else:
         raise FlowRuntimeError(
             "{} activated with zero nodes specified".format(
                 self.flow_task.name))
Ejemplo n.º 5
0
 def activate_next(self):
     if self._split_count:
         token_source = Token.split_token_source(self.task.token,
                                                 self.task.pk)
         for _ in range(self._split_count):
             self.flow_task._next.activate(prev_activation=self,
                                           token=next(token_source))
     elif self.flow_task._ifnone_next_node is not None:
         self.flow_task._ifnone_next_node.activate(prev_activation=self,
                                                   token=self.task.token)
     else:
         raise FlowRuntimeError(
             "{} activated with zero and no IfNone nodes specified".format(
                 self.flow_task.name))
Ejemplo n.º 6
0
    def prepare(self, data=None, user=None):
        """Prepare activation for execution."""
        super(ManagedStartActivation, self).prepare.original()
        self.task.owner = user

        management_form_class = self.get_management_form_class()
        self.management_form = management_form_class(data=data,
                                                     instance=self.task)

        if data:
            if not self.management_form.is_valid():
                raise FlowRuntimeError(
                    'Activation metadata is broken {}'.format(
                        self.management_form.errors))
            self.task = self.management_form.save(commit=False)
Ejemplo n.º 7
0
    def is_done(self):
        if not self.flow_task._wait_all:
            return True

        join_prefixes = set(prev.token.get_common_split_prefix()
                            for prev in self.task.previous.all())

        if len(join_prefixes) > 1:
            raise FlowRuntimeError(
                'Multiple tokens {} cames to join {}'.format(
                    join_prefixes, self.flow_task.name))

        join_token_prefix = next(iter(join_prefixes))

        active = self.flow_cls.task_cls._default_manager \
            .filter(process=self.process, token__startswith=join_token_prefix) \
            .exclude(status=Task.STATUS.FINISHED)

        return not active.exists()
Ejemplo n.º 8
0
    def is_done(self):
        """Check that process can be continued futher.

        Join check the all task state in db with the common token prefix.

        Join node would continue execution if all incoming tasks are DONE or CANCELED.
        """
        result = False

        token = self.task.token

        if self.task.token.is_split_token():
            token = token.get_base_split_token()

            join_prefixes = set(
                prev.token.get_common_split_prefix(token, prev.pk)
                for prev in self.task.previous.exclude(
                    status=STATUS.CANCELED).all())

            if len(join_prefixes) > 1:
                raise FlowRuntimeError(
                    'Multiple tokens {} came to join {}'.format(
                        join_prefixes, self.flow_task.name))

            join_token_prefix = next(iter(join_prefixes))

            active_tasks = self.flow_class.task_class._default_manager \
                .filter(process=self.process, token__startswith=join_token_prefix) \
                .exclude(status__in=[STATUS.DONE, STATUS.CANCELED])

            if not self.flow_task._wait_all:
                result = True
                # cancel other tasks
                for active_task in active_tasks:
                    active_task.status = STATUS.CANCELED
                    active_task.save()
            else:
                result = not active_tasks.exists()

        return result
Ejemplo n.º 9
0
    def activate(cls, flow_task, prev_activation, token):
        flow_cls, flow_task = flow_task.flow_cls, flow_task
        process = prev_activation.process

        # lookup for active join instance
        tasks = flow_cls.task_cls._default_manager.filter(
            flow_task=flow_task,
            process=process,
            status=flow_cls.task_cls.STATUS.STARTED)

        if len(tasks) > 1:
            raise FlowRuntimeError(
                'More than one join instance for process found')

        activation = cls()

        task = tasks.first()
        if not task:
            if token.is_split_token():
                token = token.get_base_split_token()

            task = flow_cls.task_cls(process=process,
                                     flow_task=flow_task,
                                     token=token)

            task.save()
            task.previous.add(prev_activation.task)
            activation.initialize(flow_task, task)
            activation.prepare()
            activation.start()
        else:
            activation.initialize(flow_task, task)

        if activation.is_done():
            activation.done()

        return activation
Ejemplo n.º 10
0
    def assign_tasks(self):
        with self.exception_guard():
            self._owner_list = self.flow_task.owner_list(self)

            if self._owner_list:
                token_source = Token.split_token_source(
                    self.task.token, self.task.pk)
                for owner in self._owner_list:
                    task = self.flow_class.task_class(process=self.process,
                                                      flow_task=self.flow_task,
                                                      token=next(token_source),
                                                      owner=owner,
                                                      status=STATUS.ASSIGNED,
                                                      started=timezone.now())
                    task.save()
                    task.previous.add(self.task)

            elif self.flow_task._ifnone_next_node is not None:
                self.flow_task._ifnone_next_node.activate(
                    prev_activation=self, token=self.task.token)
            else:
                raise FlowRuntimeError(
                    "{} activated with zero and no IfNone nodes specified".
                    format(self.flow_task.name))