From 33b344facbe9b693f81dbd8f7ebbb6378838822c Mon Sep 17 00:00:00 2001 From: Elijah DeLee Date: Mon, 13 May 2024 09:26:03 -0500 Subject: [PATCH] Skip 3 expensive calls for jobs saving in 'waiting' status on UnifiedJob (#15174) skip update parent logic for 'waiting' on UnifiedJob by not looking up "status_before" from previous instance we save 2 to 3 expensive calls (the self lookup of old state, the lookup of parent, and the update to parent if allow_simultaneous == False or status == 'waiting') --- awx/main/models/unified_jobs.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/awx/main/models/unified_jobs.py b/awx/main/models/unified_jobs.py index 305ca2907307..4f885585a66f 100644 --- a/awx/main/models/unified_jobs.py +++ b/awx/main/models/unified_jobs.py @@ -823,7 +823,7 @@ def parent_instance_set(key, val): update_fields.append(key) if parent_instance: - if self.status in ('pending', 'waiting', 'running'): + if self.status in ('pending', 'running'): if parent_instance.current_job != self: parent_instance_set('current_job', self) # Update parent with all the 'good' states of it's child @@ -860,7 +860,7 @@ def save(self, *args, **kwargs): # If this job already exists in the database, retrieve a copy of # the job in its prior state. # If update_fields are given without status, then that indicates no change - if self.pk and ((not update_fields) or ('status' in update_fields)): + if self.status != 'waiting' and self.pk and ((not update_fields) or ('status' in update_fields)): self_before = self.__class__.objects.get(pk=self.pk) if self_before.status != self.status: status_before = self_before.status @@ -902,7 +902,8 @@ def save(self, *args, **kwargs): update_fields.append('elapsed') # Ensure that the job template information is current. - if self.unified_job_template != self._get_parent_instance(): + # unless status is 'waiting', because this happens in large batches at end of task manager runs and is blocking + if self.status != 'waiting' and self.unified_job_template != self._get_parent_instance(): self.unified_job_template = self._get_parent_instance() if 'unified_job_template' not in update_fields: update_fields.append('unified_job_template') @@ -915,8 +916,9 @@ def save(self, *args, **kwargs): # Okay; we're done. Perform the actual save. result = super(UnifiedJob, self).save(*args, **kwargs) - # If status changed, update the parent instance. - if self.status != status_before: + # If status changed, update the parent instance + # unless status is 'waiting', because this happens in large batches at end of task manager runs and is blocking + if self.status != status_before and self.status != 'waiting': # Update parent outside of the transaction for Job w/ allow_simultaneous=True # This dodges lock contention at the expense of the foreign key not being # completely correct.