From 1bb6c17fe27d0deacc3bd0a3b763903fa35725df Mon Sep 17 00:00:00 2001 From: Ryan Petrello Date: Wed, 13 Sep 2017 23:00:48 -0400 Subject: [PATCH 1/2] trick django-polymorphic into allowing `defer()` on polymorphic objects django-polymorphic itself generates queries for polymorphic object lookups, and these queries for UnifiedJob are *not* properly defering the `result_stdout_text` column, resulting in more very slow queries. This solution is _very_ hacky, and very specific to this specific version of Django and django-polymorphic, but it works until we can solve this problem the proper way in 3.3 (by removing large stdout blobs from the database). see: https://github.com/ansible/ansible-tower/issues/7568 --- awx/main/models/__init__.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/awx/main/models/__init__.py b/awx/main/models/__init__.py index 01bd68cc66..c044997fca 100644 --- a/awx/main/models/__init__.py +++ b/awx/main/models/__init__.py @@ -145,3 +145,15 @@ activity_stream_registrar.connect(WorkflowJob) # prevent API filtering on certain Django-supplied sensitive fields prevent_search(User._meta.get_field('password')) + +# Always, always, always defer result_stdout_text for polymorphic UnifiedJob rows +def defer_stdout(f): + def _wrapped(*args, **kwargs): + objs = f(*args, **kwargs) + objs.query.deferred_loading[0].add('result_stdout_text') + return objs + return _wrapped + + +for cls in UnifiedJob.__subclasses__(): + cls.base_objects.filter = defer_stdout(cls.base_objects.filter) From 7a958a1af1b7718f520d2a68cdab6370d6b64da8 Mon Sep 17 00:00:00 2001 From: Ryan Petrello Date: Thu, 14 Sep 2017 13:52:09 -0400 Subject: [PATCH 2/2] more result_stdout_text defer optimization for inventory updates see: https://github.com/ansible/ansible-tower/issues/7568 --- awx/api/views.py | 6 ++++++ awx/main/access.py | 1 + awx/main/models/__init__.py | 1 + 3 files changed, 8 insertions(+) diff --git a/awx/api/views.py b/awx/api/views.py index 0930e5e71b..c10a5654d2 100644 --- a/awx/api/views.py +++ b/awx/api/views.py @@ -2670,6 +2670,12 @@ class InventoryUpdateList(ListAPIView): model = InventoryUpdate serializer_class = InventoryUpdateListSerializer + def get_queryset(self): + qs = super(InventoryUpdateList, self).get_queryset() + # TODO: remove this defer in 3.3 when we implement https://github.com/ansible/ansible-tower/issues/5436 + qs = qs.defer('result_stdout_text') + return qs + class InventoryUpdateDetail(UnifiedJobDeletionMixin, RetrieveDestroyAPIView): diff --git a/awx/main/access.py b/awx/main/access.py index 8297d2ba70..c2dae1397c 100644 --- a/awx/main/access.py +++ b/awx/main/access.py @@ -2084,6 +2084,7 @@ class UnifiedJobAccess(BaseAccess): # 'job_template__project', # 'job_template__credential', #) + # TODO: remove this defer in 3.3 when we implement https://github.com/ansible/ansible-tower/issues/5436 qs = qs.defer('result_stdout_text') return qs.all() diff --git a/awx/main/models/__init__.py b/awx/main/models/__init__.py index c044997fca..2443e16f45 100644 --- a/awx/main/models/__init__.py +++ b/awx/main/models/__init__.py @@ -147,6 +147,7 @@ activity_stream_registrar.connect(WorkflowJob) prevent_search(User._meta.get_field('password')) # Always, always, always defer result_stdout_text for polymorphic UnifiedJob rows +# TODO: remove this defer in 3.3 when we implement https://github.com/ansible/ansible-tower/issues/5436 def defer_stdout(f): def _wrapped(*args, **kwargs): objs = f(*args, **kwargs)