Skip to content

Commit 711b018

Browse files
authored
cache dashboard query (#16165)
This causes an expensive query and the view sometimes called excessively by the UI. Memoize per unique user and params (time period) for 15s.
1 parent be30a75 commit 711b018

File tree

1 file changed

+20
-4
lines changed

1 file changed

+20
-4
lines changed

awx/api/views/__init__.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@
9797
from awx.main.utils.encryption import encrypt_value
9898
from awx.main.utils.filters import SmartFilter
9999
from awx.main.utils.plugins import compute_cloud_inventory_sources
100+
from awx.main.utils.common import memoize
100101
from awx.main.redact import UriCleaner
101102
from awx.api.permissions import (
102103
JobTemplateCallbackPermission,
@@ -271,7 +272,24 @@ def get(self, request, format=None):
271272
period = request.query_params.get('period', 'month')
272273
job_type = request.query_params.get('job_type', 'all')
273274

274-
user_unified_jobs = get_user_queryset(request.user, models.UnifiedJob).exclude(launch_type='sync')
275+
user_id = getattr(request.user, 'id', None) or 0
276+
try:
277+
payload = self._compute_dashboard_jobs_graph(user_id, period, job_type)
278+
except ParseError as exc:
279+
return Response({'error': str(exc)}, status=status.HTTP_400_BAD_REQUEST)
280+
return Response(payload)
281+
282+
@staticmethod
283+
@memoize(ttl=15)
284+
def _compute_dashboard_jobs_graph(user_id, period, job_type):
285+
# Debug log when there is a cache miss
286+
logger.debug('DashboardJobsGraphView cache miss: user_id=%s period=%s job_type=%s', user_id, period, job_type)
287+
# Validate period. Raise exception to let caller return 400 error in response
288+
if period not in ('month', 'two_weeks', 'week', 'day'):
289+
raise ParseError(_('Unknown period "%s"') % str(period))
290+
291+
user = models.User.objects.get(pk=user_id) if user_id else None
292+
user_unified_jobs = get_user_queryset(user, models.UnifiedJob).exclude(launch_type='sync')
275293

276294
success_query = user_unified_jobs.filter(status='successful')
277295
failed_query = user_unified_jobs.filter(status='failed')
@@ -305,8 +323,6 @@ def get(self, request, format=None):
305323
elif period == 'day':
306324
start = end - dateutil.relativedelta.relativedelta(days=1)
307325
interval = 'hour'
308-
else:
309-
return Response({'error': _('Unknown period "%s"') % str(period)}, status=status.HTTP_400_BAD_REQUEST)
310326

311327
dashboard_data = {"jobs": {"successful": [], "failed": [], "canceled": [], "error": []}}
312328

@@ -358,7 +374,7 @@ def get(self, request, format=None):
358374
canceled_list.append([time.mktime(date.timetuple()), data_c.get(date, 0)])
359375
error_list.append([time.mktime(date.timetuple()), data_e.get(date, 0)])
360376

361-
return Response(dashboard_data)
377+
return dashboard_data
362378

363379

364380
class InstanceList(ListCreateAPIView):

0 commit comments

Comments
 (0)