summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan McGee <dan@archlinux.org>2011-08-17 09:01:07 -0500
committerDan McGee <dan@archlinux.org>2011-08-17 09:01:07 -0500
commitc80afa08c7aec23984e84bfb3ab5683c9c392115 (patch)
treefa477a892d12edef331b25aeeeb85722d94f76cd
parent61311701a51cc5b060d5baa56536805aa271f9d6 (diff)
releng: refactor results overview page for performance
Use some annotation stuff and trickeration to reduce the number of queries we need on the results overview page by quite a bit. Signed-off-by: Dan McGee <dan@archlinux.org>
-rw-r--r--releng/models.py26
-rw-r--r--releng/views.py49
2 files changed, 41 insertions, 34 deletions
diff --git a/releng/models.py b/releng/models.py
index 3afef55e..a958288b 100644
--- a/releng/models.py
+++ b/releng/models.py
@@ -10,36 +10,10 @@ class IsoOption(models.Model):
def __unicode__(self):
return self.name
- def get_test_result(self, success):
- try:
- return self.test_set.filter(success=success).select_related(
- 'iso').latest('iso__id').iso
- except Test.DoesNotExist:
- return None
-
- def get_last_success(self):
- return self.get_test_result(True)
-
- def get_last_failure(self):
- return self.get_test_result(False)
-
class Meta:
abstract = True
class RollbackOption(IsoOption):
- def get_rollback_test_result(self, success):
- try:
- return self.rollback_test_set.filter(success=success).select_related(
- 'iso').latest('iso__id').iso
- except Test.DoesNotExist:
- return None
-
- def get_last_rollback_success(self):
- return self.get_rollback_test_result(True)
-
- def get_last_rollback_failure(self):
- return self.get_rollback_test_result(False)
-
class Meta:
abstract = True
diff --git a/releng/views.py b/releng/views.py
index 796fc044..7f895a45 100644
--- a/releng/views.py
+++ b/releng/views.py
@@ -1,6 +1,6 @@
from django import forms
from django.conf import settings
-from django.db.models import Count
+from django.db.models import Count, Max
from django.http import Http404
from django.shortcuts import get_object_or_404, redirect
from django.views.generic.simple import direct_to_template
@@ -85,18 +85,49 @@ def calculate_option_overview(field_name):
'is_rollback': is_rollback,
'values': []
}
+ if not is_rollback:
+ successes = dict(model.objects.values_list('pk').filter(
+ test__success=True).annotate(latest=Max('test__iso__id')))
+ failures = dict(model.objects.values_list('pk').filter(
+ test__success=False).annotate(latest=Max('test__iso__id')))
+ else:
+ successes = dict(model.objects.values_list('pk').filter(
+ rollback_test_set__success=True).annotate(
+ latest=Max('rollback_test_set__iso__id')))
+ failures = dict(model.objects.values_list('pk').filter(
+ rollback_test_set__success=False).annotate(
+ latest=Max('rollback_test_set__iso__id')))
+
for value in model.objects.all():
- data = { 'value': value }
- if is_rollback:
- data['success'] = value.get_last_rollback_success()
- data['failure'] = value.get_last_rollback_failure()
- else:
- data['success'] = value.get_last_success()
- data['failure'] = value.get_last_failure()
+ data = {
+ 'value': value,
+ 'success': successes.get(value.pk),
+ 'failure': failures.get(value.pk),
+ }
option['values'].append(data)
return option
+def options_fetch_iso(options):
+ '''Replaces the Iso PK with a full Iso model object in a list of options
+ used on the overview page. We do it this way to only have to query the Iso
+ table once rather than once per option.'''
+ # collect all necessary Iso PKs
+ all_pks = set()
+ for option in options:
+ all_pks.update(v['success'] for v in option['values'])
+ all_pks.update(v['failure'] for v in option['values'])
+
+ all_pks.discard(None)
+ all_isos = Iso.objects.in_bulk(all_pks)
+
+ for option in options:
+ for value in option['values']:
+ value['success'] = all_isos.get(value['success'])
+ value['failure'] = all_isos.get(value['failure'])
+
+ return options
+
def test_results_overview(request):
# data structure produced:
# [ { option, name, is_rollback, values: [ { value, success, failure } ... ] } ... ]
@@ -107,6 +138,8 @@ def test_results_overview(request):
for field in fields:
all_options.append(calculate_option_overview(field))
+ all_options = options_fetch_iso(all_options)
+
context = {
'options': all_options,
'iso_url': settings.ISO_LIST_URL,