From 93c2a5e31cf9884dff0c3e15244e7be824783d4c Mon Sep 17 00:00:00 2001 From: Matthew Jones Date: Tue, 13 May 2014 15:12:42 -0400 Subject: [PATCH] Improve update computed field signaling so that we only emit signals when a host is added or deleted, or if it is associated or disassociated, or if a job runs Conflicts: awx/main/signals.py --- awx/main/models/inventory.py | 16 +++++++++------- awx/main/signals.py | 29 ++++++++++++++++++++++++----- awx/main/tasks.py | 8 +++++++- 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index 31aab52e12..c71d7f90b4 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -263,12 +263,13 @@ class Host(CommonModelNameNotUnique): self.save(update_fields=computed_fields.keys()) # Groups and inventory may also need to be updated when host fields # change. - if update_groups: - for group in self.all_groups.filter(active=True): - group.update_computed_fields() - if update_inventory: - self.inventory.update_computed_fields(update_groups=False, - update_hosts=False) + # NOTE: I think this is no longer needed + # if update_groups: + # for group in self.all_groups.filter(active=True): + # group.update_computed_fields() + # if update_inventory: + # self.inventory.update_computed_fields(update_groups=False, + # update_hosts=False) # Rebuild summary fields cache self.update_cached_values() variables_dict = VarsDictProperty('variables') @@ -391,6 +392,7 @@ class Group(CommonModelNameNotUnique): return reverse('api:group_detail', args=(self.pk,)) def mark_inactive_recursive(self, parent=None): + from awx.main.tasks import update_inventory_computed_fields def mark_actual(parent=parent): linked_children = [(parent, self)] + [(self, child) for child in self.children.all()] marked_groups = [] @@ -418,7 +420,7 @@ class Group(CommonModelNameNotUnique): host.mark_inactive() with ignore_inventory_computed_fields(): mark_actual() - self.inventory.update_computed_fields() + update_inventory_computed_fields.delay(self.id, True) def mark_inactive(self, save=True, recompute=True): ''' diff --git a/awx/main/signals.py b/awx/main/signals.py index 33a8fab4e5..9534af4580 100644 --- a/awx/main/signals.py +++ b/awx/main/signals.py @@ -82,12 +82,31 @@ def emit_update_inventory_computed_fields(sender, **kwargs): except Inventory.DoesNotExist: pass else: - update_inventory_computed_fields.delay(inventory.id, issubclass(sender, Job)) + update_inventory_computed_fields.delay(inventory.id, True) -post_save.connect(emit_update_inventory_computed_fields, sender=Host) -post_delete.connect(emit_update_inventory_computed_fields, sender=Host) -post_save.connect(emit_update_inventory_computed_fields, sender=Group) -post_delete.connect(emit_update_inventory_computed_fields, sender=Group) +def emit_update_inventory_on_created_or_deleted(sender, **kwargs): + if getattr(_inventory_updates, 'is_updating', False): + return + instance = kwargs['instance'] + if kwargs['created'] or not instance.active or kwargs['signal'] == post_delete: + pass + else: + return + sender_name = unicode(sender._meta.verbose_name) + logger.debug("%s created or deleted, updating inventory computed fields: %r %r", + sender_name, sender, kwargs) + try: + inventory = instance.inventory + except Inventory.DoesNotExist: + pass + else: + update_inventory_computed_fields.delay(inventory.id, True) + + +post_save.connect(emit_update_inventory_on_created_or_deleted, sender=Host) +post_delete.connect(emit_update_inventory_on_created_or_deleted, sender=Host) +post_save.connect(emit_update_inventory_on_created_or_deleted, sender=Group) +post_delete.connect(emit_update_inventory_on_created_or_deleted, sender=Group) m2m_changed.connect(emit_update_inventory_computed_fields, sender=Group.hosts.through) m2m_changed.connect(emit_update_inventory_computed_fields, sender=Group.parents.through) m2m_changed.connect(emit_update_inventory_computed_fields, sender=Host.inventory_sources.through) diff --git a/awx/main/tasks.py b/awx/main/tasks.py index f961b1143d..85ed5f2d34 100644 --- a/awx/main/tasks.py +++ b/awx/main/tasks.py @@ -127,7 +127,7 @@ def handle_work_error(self, task_id, subtasks=None): instance.socketio_emit_status("failed") @task() -def update_inventory_computed_fields(inventory_id, should_update_hosts): +def update_inventory_computed_fields(inventory_id, should_update_hosts=True): ''' Signal handler and wrapper around inventory.update_computed_fields to prevent unnecessary recursive calls. @@ -589,6 +589,12 @@ class RunJob(BaseTask): Hook for actions to run after job/task has completed. ''' super(RunJob, self).post_run_hook(job, **kwargs) + try: + inventory = job.inventory + except Inventory.DoesNotExist: + pass + else: + update_inventory_computed_fields.delay(inventory.id, True) # Update job event fields after job has completed (only when using REST # API callback). if not settings.CALLBACK_CONSUMER_PORT: