Add new attach_maintainers() utility method
This allows us to alleviate the N+1 query problem when we want maintainer data for a queryset of packages. We use it on signoffs here; we should also be able to apply this to the todolist section where this problem has existed for some time. Signed-off-by: Dan McGee <dan@archlinux.org>
This commit is contained in:
parent
278d74b1d1
commit
19c2841f20
@ -206,11 +206,19 @@ def get_full_url(self, proto='https'):
|
||||
def is_signed(self):
|
||||
return bool(self.pgp_signature)
|
||||
|
||||
_maintainers = None
|
||||
|
||||
@property
|
||||
def maintainers(self):
|
||||
return User.objects.filter(
|
||||
package_relations__pkgbase=self.pkgbase,
|
||||
package_relations__type=PackageRelation.MAINTAINER)
|
||||
if self._maintainers is None:
|
||||
self._maintainers = User.objects.filter(
|
||||
package_relations__pkgbase=self.pkgbase,
|
||||
package_relations__type=PackageRelation.MAINTAINER)
|
||||
return self._maintainers
|
||||
|
||||
@maintainers.setter
|
||||
def maintainers(self, maintainers):
|
||||
self._maintainers = maintainers
|
||||
|
||||
@cache_function(300)
|
||||
def applicable_arches(self):
|
||||
|
@ -1,3 +1,4 @@
|
||||
from collections import defaultdict
|
||||
from operator import itemgetter
|
||||
|
||||
from django.db import connection
|
||||
@ -127,6 +128,7 @@ def get_differences_info(arch_a, arch_b):
|
||||
differences.sort(key=lambda a: (a.repo.name, a.pkgname))
|
||||
return differences
|
||||
|
||||
|
||||
def get_wrong_permissions():
|
||||
sql = """
|
||||
SELECT DISTINCT id
|
||||
@ -150,6 +152,32 @@ def get_wrong_permissions():
|
||||
return relations
|
||||
|
||||
|
||||
def attach_maintainers(packages):
|
||||
'''Given a queryset or something resembling it of package objects, find all
|
||||
the maintainers and attach them to the packages to prevent N+1 query
|
||||
cascading.'''
|
||||
pkgbases = set(p.pkgbase for p in packages)
|
||||
rels = PackageRelation.objects.filter(type=PackageRelation.MAINTAINER,
|
||||
pkgbase__in=pkgbases).values_list('pkgbase', 'user_id').distinct()
|
||||
|
||||
# get all the user objects we will need
|
||||
user_ids = set(rel[1] for rel in rels)
|
||||
users = User.objects.in_bulk(user_ids)
|
||||
|
||||
# now build a pkgbase -> [maintainers...] map
|
||||
maintainers = defaultdict(list)
|
||||
for rel in rels:
|
||||
maintainers[rel[0]].append(users[rel[1]])
|
||||
|
||||
annotated = []
|
||||
# and finally, attach the maintainer lists on the original packages
|
||||
for package in packages:
|
||||
package.maintainers = maintainers[package.pkgbase]
|
||||
annotated.append(package)
|
||||
|
||||
return annotated
|
||||
|
||||
|
||||
def approved_by_signoffs(signoffs, spec):
|
||||
if signoffs:
|
||||
good_signoffs = sum(1 for s in signoffs if not s.revoked)
|
||||
@ -173,9 +201,7 @@ def __init__(self, packages):
|
||||
self.version = ''
|
||||
self.last_update = first.last_update
|
||||
self.packager = first.packager
|
||||
self.maintainers = User.objects.filter(
|
||||
package_relations__type=PackageRelation.MAINTAINER,
|
||||
package_relations__pkgbase=self.pkgbase)
|
||||
self.maintainers = first.maintainers
|
||||
|
||||
self.specification = \
|
||||
SignoffSpecification.objects.get_or_default_from_package(first)
|
||||
@ -236,6 +262,7 @@ def __unicode__(self):
|
||||
|
||||
def get_current_signoffs(repos):
|
||||
'''Returns a mapping of pkgbase -> signoff objects for the given repos.'''
|
||||
# TODO this isn't current at all- this is every single signoff...
|
||||
cursor = connection.cursor()
|
||||
sql = """
|
||||
SELECT DISTINCT s.id
|
||||
@ -274,6 +301,7 @@ def get_signoff_groups(repos=None):
|
||||
test_pkgs = Package.objects.select_related(
|
||||
'arch', 'repo', 'packager').filter(repo__in=repo_ids)
|
||||
packages = test_pkgs.order_by('pkgname')
|
||||
packages = attach_maintainers(packages)
|
||||
|
||||
# Collect all pkgbase values in testing repos
|
||||
q_pkgbase = test_pkgs.values('pkgbase')
|
||||
|
Loading…
Reference in New Issue
Block a user