mirror of
https://github.com/ansible/awx.git
synced 2026-02-15 10:10:01 -03:30
Optimize object creation by getting fewer empty relationships (#12508)
This optimizes the ActivityStreamSerializer by only getting many-to-many relationships that are speculatively non-empty based on information we have in other fields We run this every time we create an object as an on_commit action so it is expected this will have a major impact on response times for launching jobs
This commit is contained in:
@@ -29,7 +29,6 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
from django.utils.encoding import force_str
|
from django.utils.encoding import force_str
|
||||||
from django.utils.text import capfirst
|
from django.utils.text import capfirst
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
from django.utils.functional import cached_property
|
|
||||||
|
|
||||||
# Django REST Framework
|
# Django REST Framework
|
||||||
from rest_framework.exceptions import ValidationError, PermissionDenied
|
from rest_framework.exceptions import ValidationError, PermissionDenied
|
||||||
@@ -5008,8 +5007,7 @@ class ActivityStreamSerializer(BaseSerializer):
|
|||||||
object_association = serializers.SerializerMethodField(help_text=_("When present, shows the field name of the role or relationship that changed."))
|
object_association = serializers.SerializerMethodField(help_text=_("When present, shows the field name of the role or relationship that changed."))
|
||||||
object_type = serializers.SerializerMethodField(help_text=_("When present, shows the model on which the role or relationship was defined."))
|
object_type = serializers.SerializerMethodField(help_text=_("When present, shows the model on which the role or relationship was defined."))
|
||||||
|
|
||||||
@cached_property
|
def _local_summarizable_fk_fields(self, obj):
|
||||||
def _local_summarizable_fk_fields(self):
|
|
||||||
summary_dict = copy.copy(SUMMARIZABLE_FK_FIELDS)
|
summary_dict = copy.copy(SUMMARIZABLE_FK_FIELDS)
|
||||||
# Special requests
|
# Special requests
|
||||||
summary_dict['group'] = summary_dict['group'] + ('inventory_id',)
|
summary_dict['group'] = summary_dict['group'] + ('inventory_id',)
|
||||||
@@ -5029,7 +5027,13 @@ class ActivityStreamSerializer(BaseSerializer):
|
|||||||
('workflow_approval', ('id', 'name', 'unified_job_id')),
|
('workflow_approval', ('id', 'name', 'unified_job_id')),
|
||||||
('instance', ('id', 'hostname')),
|
('instance', ('id', 'hostname')),
|
||||||
]
|
]
|
||||||
return field_list
|
# Optimization - do not attempt to summarize all fields, pair down to only relations that exist
|
||||||
|
if not obj:
|
||||||
|
return field_list
|
||||||
|
existing_association_types = [obj.object1, obj.object2]
|
||||||
|
if 'user' in existing_association_types:
|
||||||
|
existing_association_types.append('role')
|
||||||
|
return [entry for entry in field_list if entry[0] in existing_association_types]
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ActivityStream
|
model = ActivityStream
|
||||||
@@ -5113,7 +5117,7 @@ class ActivityStreamSerializer(BaseSerializer):
|
|||||||
data = {}
|
data = {}
|
||||||
if obj.actor is not None:
|
if obj.actor is not None:
|
||||||
data['actor'] = self.reverse('api:user_detail', kwargs={'pk': obj.actor.pk})
|
data['actor'] = self.reverse('api:user_detail', kwargs={'pk': obj.actor.pk})
|
||||||
for fk, __ in self._local_summarizable_fk_fields:
|
for fk, __ in self._local_summarizable_fk_fields(obj):
|
||||||
if not hasattr(obj, fk):
|
if not hasattr(obj, fk):
|
||||||
continue
|
continue
|
||||||
m2m_list = self._get_related_objects(obj, fk)
|
m2m_list = self._get_related_objects(obj, fk)
|
||||||
@@ -5170,7 +5174,7 @@ class ActivityStreamSerializer(BaseSerializer):
|
|||||||
|
|
||||||
def get_summary_fields(self, obj):
|
def get_summary_fields(self, obj):
|
||||||
summary_fields = OrderedDict()
|
summary_fields = OrderedDict()
|
||||||
for fk, related_fields in self._local_summarizable_fk_fields:
|
for fk, related_fields in self._local_summarizable_fk_fields(obj):
|
||||||
try:
|
try:
|
||||||
if not hasattr(obj, fk):
|
if not hasattr(obj, fk):
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -409,7 +409,7 @@ def emit_activity_stream_change(instance):
|
|||||||
from awx.api.serializers import ActivityStreamSerializer
|
from awx.api.serializers import ActivityStreamSerializer
|
||||||
|
|
||||||
actor = None
|
actor = None
|
||||||
if instance.actor:
|
if instance.actor_id:
|
||||||
actor = instance.actor.username
|
actor = instance.actor.username
|
||||||
summary_fields = ActivityStreamSerializer(instance).get_summary_fields(instance)
|
summary_fields = ActivityStreamSerializer(instance).get_summary_fields(instance)
|
||||||
analytics_logger.info(
|
analytics_logger.info(
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ def test_activity_stream_related():
|
|||||||
"""
|
"""
|
||||||
serializer_related = set(
|
serializer_related = set(
|
||||||
ActivityStream._meta.get_field(field_name).related_model
|
ActivityStream._meta.get_field(field_name).related_model
|
||||||
for field_name, stuff in ActivityStreamSerializer()._local_summarizable_fk_fields
|
for field_name, stuff in ActivityStreamSerializer()._local_summarizable_fk_fields(None)
|
||||||
if hasattr(ActivityStream, field_name)
|
if hasattr(ActivityStream, field_name)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user