Repository: ansible/awx
File: awx/main/scheduler/task_manager.py (Python)

Code before:
        then we don't need to create one
        '''
        if latest_project_update.status in ['waiting', 'pending', 'running']:
            return False

        '''
        If the latest project update has a created time == job_created_time-1
        then consider the project update found. This is so we don't enter an infinite loop
        of updating the project when cache timeout is 0.
        '''
        if (
            latest_project_update.project.scm_update_cache_timeout == 0
            and latest_project_update.launch_type == 'dependency'
            and latest_project_update.created == job.created - timedelta(seconds=1)
        ):
            return False
        '''
        Normal Cache Timeout Logic
        '''
        timeout_seconds = timedelta(seconds=latest_project_update.project.scm_update_cache_timeout)
        if (latest_project_update.finished + timeout_seconds) < now:
            return True
        return False

    def generate_dependencies(self, undeped_tasks):
        created_dependencies = []
        for task in undeped_tasks:
            task.log_lifecycle("acknowledged")
            dependencies = []
            if not type(task) is Job:
                continue
            # TODO: Can remove task.project None check after scan-job-default-playbook is removed
            if task.project is not None and task.project.scm_update_on_launch is True:
                latest_project_update = self.get_latest_project_update(task.project_id)
                if self.should_update_related_project(task, latest_project_update):
                    project_task = self.create_project_update(task)
                    created_dependencies.append(project_task)
                    dependencies.append(project_task)
                else:
                    dependencies.append(latest_project_update)

            # Inventory created 2 seconds behind job
            try:
                start_args = json.loads(decrypt_field(task, field_name="start_args"))
            except ValueError:
                start_args = dict()
            for inventory_source in [invsrc for invsrc in self.all_inventory_sources if invsrc.inventory == task.inventory]:
                if "inventory_sources_already_updated" in start_args and inventory_source.id in start_args['inventory_sources_already_updated']:
                    continue
                if not inventory_source.update_on_launch:
                    continue

Review comment (suggestion):
This could still need more work to avoid spawning the same update twice when the playbook comes from the same project. There's also an optimization issue here, because if the inventory update was just spawned, you would already have the update in memory, but this would re-fetch it.

Code after:
        Normal Cache Timeout Logic
        '''
        timeout_seconds = timedelta(seconds=latest_project_update.project.scm_update_cache_timeout)
        if (latest_project_update.finished + timeout_seconds) < now:
            return True
        return False

    def gen_dep_for_job(self, task):
        created_dependencies = []
        dependencies = []
        # TODO: Can remove task.project None check after scan-job-default-playbook is removed
        if task.project is not None and task.project.scm_update_on_launch is True:
            latest_project_update = self.get_latest_project_update(task.project_id)
            if self.should_update_related_project(task, latest_project_update):
                latest_project_update = self.create_project_update(task)
                created_dependencies.append(latest_project_update)
            dependencies.append(latest_project_update)

        # Inventory created 2 seconds behind job
        try:
            start_args = json.loads(decrypt_field(task, field_name="start_args"))
        except ValueError:
            start_args = dict()
        # generator for inventory sources related to this task
        task_inv_sources = (invsrc for invsrc in self.all_inventory_sources if invsrc.inventory_id == task.inventory_id)
        for inventory_source in task_inv_sources:
            if "inventory_sources_already_updated" in start_args and inventory_source.id in start_args['inventory_sources_already_updated']:
                continue
            if not inventory_source.update_on_launch:
                continue
            latest_inventory_update = self.get_latest_inventory_update(inventory_source)
            if self.should_update_inventory_source(task, latest_inventory_update):
                inventory_task = self.create_inventory_update(task, inventory_source)
                created_dependencies.append(inventory_task)
                dependencies.append(inventory_task)
            else:
                dependencies.append(latest_inventory_update)

        if dependencies:
            self.add_dependencies(task, dependencies)

        return created_dependencies

    def gen_dep_for_inventory_update(self, inventory_task):
        created_dependencies = []
        if inventory_task.source == "scm":
            invsrc = inventory_task.inventory_source
            if not invsrc.source_project.scm_update_on_launch:
                return created_dependencies

            latest_src_project_update = self.get_latest_project_update(invsrc.source_project_id)