move legacy UnifiedJob stdout data to a separate unmanaged model

This data often (in the case of inventory updates) represents large data
blobs (5+MB per job run).  Storing it on the polymorphic base class
table, `main_unifiedjob`, causes it to be automatically fetched on every
query (and every polymorphic join) against that table, which can result
in _very_ poor performance for awx across the board.  Django offers
`defer()`, but it's quite complicated to sprinkle this everywhere (and
easy to get wrong/introduce side effects related to our RBAC and usage
of polymorphism).

This change moves the field definition to a separate unmanaged model
(which references the same underlying `main_unifiedjob` table) and adds
a proxy for fetching the data as needed

see https://github.com/ansible/awx/issues/200
This commit is contained in:
Ryan Petrello
2017-12-12 14:41:42 -05:00
parent 2c64a2ce63
commit 202161f090
9 changed files with 108 additions and 41 deletions

View File

@@ -492,6 +492,18 @@ class UnifiedJobTypeStringMixin(object):
return UnifiedJobTypeStringMixin._camel_to_underscore(self.__class__.__name__)
class UnifiedJobDeprecatedStdout(models.Model):
class Meta:
managed = False
db_table = 'main_unifiedjob'
result_stdout_text = models.TextField(
null=True,
editable=False,
)
class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique, UnifiedJobTypeStringMixin, TaskManagerUnifiedJobMixin):
'''
Concrete base class for unified job run by the task engine.
@@ -620,11 +632,6 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique
default='',
editable=False,
))
result_stdout_text = models.TextField(
blank=True,
default='',
editable=False,
)
result_stdout_file = models.TextField( # FilePathfield?
blank=True,
default='',
@@ -882,6 +889,19 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique
config.credentials.add(*job_creds)
return config
@property
def result_stdout_text(self):
related = UnifiedJobDeprecatedStdout.objects.get(pk=self.pk)
return related.result_stdout_text or ''
@result_stdout_text.setter
def result_stdout_text(self, value):
# TODO: remove this method once all stdout is based on jobevents
# (because it won't be used for writing anymore)
related = UnifiedJobDeprecatedStdout.objects.get(pk=self.pk)
related.result_stdout_text = value
related.save()
def result_stdout_raw_handle(self, attempt=0):
"""Return a file-like object containing the standard out of the
job's result.