Beispiel #1
0
    def enqueue_task(self, execution_plan, task_name, circular_check=None):
        if not self.has_task(task_name):
            raise NoSuchTaskException(task_name)

        task = self.get_task(task_name)

        if task == circular_check:
            raise CircularTaskDependencyException(task.name)

        if task in execution_plan:
            return

        try:
            for dependency in self._task_dependencies[task.name]:
                self.enqueue_task(
                    execution_plan,
                    dependency.name,
                    circular_check=circular_check if circular_check else task)
        except CircularTaskDependencyException as e:
            if e.second:
                raise
            raise CircularTaskDependencyException(e.first, task.name)

        execution_plan.append(task)
Beispiel #2
0
    def build_execution_plan(self, task_names):
        self.assert_dependencies_resolved()

        execution_plan = []

        dependency_edges = {}
        for task in self.collect_all_transitive_tasks(as_list(task_names)):
            dependency_edges[task.name] = task.dependencies
        try:
            Graph(dependency_edges).assert_no_cycles_present()
        except GraphHasCycles as cycles:
            raise CircularTaskDependencyException(str(cycles))

        for task_name in as_list(task_names):
            self.enqueue_task(execution_plan, task_name)
        return execution_plan
Beispiel #3
0
    def build_shortest_execution_plan(self, task_names):
        """
        Finds the shortest execution plan taking into the account tasks already executed
        This is useful when you want to execute tasks dynamically without repeating pre-requisite
        tasks you've already executed
        """
        execution_plan = self.build_execution_plan(task_names)
        shortest_plan = copy.copy(execution_plan)
        for executed_task in self._tasks_executed:
            candidate_task = shortest_plan[0]
            if candidate_task.name not in task_names and candidate_task == executed_task:
                shortest_plan.pop(0)
            else:
                break

        if self._current_task and self._current_task in shortest_plan:
            raise CircularTaskDependencyException("Task '%s' attempted to invoke tasks %s, "
                                                  "resulting in plan %s, creating circular dependency" %
                                                  (self._current_task, task_names, shortest_plan))
        return shortest_plan