From bd2c6d255990e8dc7dacc3fd07778c347db3e4db Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sat, 20 Jul 2024 14:50:46 +0200 Subject: [PATCH 1/5] ruff: add django rules --- ruff.toml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ruff.toml b/ruff.toml index 4d85bad7..71e20fe2 100644 --- a/ruff.toml +++ b/ruff.toml @@ -5,6 +5,7 @@ select = [ "A", # flake8-builtins "B", # flake8-bugbear "C4", # flake8-comprehensions + "DJ", # flake8-django "E", # pycodestyle "F", # pyflakes "G", # flake8-logging-format @@ -27,4 +28,9 @@ ignore = [ "E731", # Do not assign a `lambda` expression, use a `def` "B904", # Within an `except` clause, raise exceptions with `raise ... from err` "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` + # TODO: add these one by one + "DJ001", # Avoid using `null=True` on string-based fields such as `CharField` + "DJ006", # Do not use `exclude` with `ModelForm`, use `fields` instead + "DJ008", # Model does not define `__str__` method + "DJ012", # Order of model's inner classes, methods, and fields does not follow the Django Style Guide: `Meta` class should come before `get_absolute_url` ] From 45b58317c13f80e7ce6439439fa05e104e9d362f Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sat, 20 Jul 2024 15:45:09 +0200 Subject: [PATCH 2/5] public: prefetch the userprofile table We request all pgp_key's in a loop which would lead to 100 queries, prefetching the userprofile makes the page load with 26 queries as of writing. --- public/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/views.py b/public/views.py index e2cd0c10..6c2c8bab 100644 --- a/public/views.py +++ b/public/views.py @@ -93,7 +93,7 @@ def feeds(request): def keys(request): profile_ids = UserProfile.allowed_repos.through.objects.values('userprofile_id') users = User.objects.filter( - is_active=True, userprofile__id__in=profile_ids).order_by('first_name', 'last_name') + is_active=True, userprofile__id__in=profile_ids).order_by('first_name', 'last_name').select_related('userprofile') user_key_ids = frozenset(user.userprofile.pgp_key[-16:] for user in users if user.userprofile.pgp_key) From 1ac7d5837fc5e8294db0615f773aea577ec9ddfc Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sat, 20 Jul 2024 16:03:14 +0200 Subject: [PATCH 3/5] packages: avoid fetching rebuilderd status on HEAD requests --- packages/views/display.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/views/display.py b/packages/views/display.py index 7f15d091..5f6778b4 100644 --- a/packages/views/display.py +++ b/packages/views/display.py @@ -128,13 +128,14 @@ def details(request, name='', repo='', arch=''): pkg = Package.objects.select_related( 'arch', 'repo', 'packager').get(pkgname=name, repo=repo_obj, arch=arch_obj) + if request.method == 'HEAD': + return empty_response() + rbstatus = None try: rbstatus = RebuilderdStatus.objects.get(pkg=pkg) except RebuilderdStatus.DoesNotExist: pass - if request.method == 'HEAD': - return empty_response() return render(request, 'packages/details.html', {'pkg': pkg, 'rbstatus': rbstatus, 'notreproducible': rbstatus.status == RebuilderdStatus.BAD if rbstatus else False}) except Package.DoesNotExist: From d813157b705a4b78d09401faf9111a8f89b9ef7d Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sat, 20 Jul 2024 16:05:14 +0200 Subject: [PATCH 4/5] packages: don't fetch rebuilderd status for non-logged in users The rebuilderd status is only shown for logged in users so fetching this is unneeded. --- packages/views/display.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/views/display.py b/packages/views/display.py index 5f6778b4..9bad3e88 100644 --- a/packages/views/display.py +++ b/packages/views/display.py @@ -132,10 +132,11 @@ def details(request, name='', repo='', arch=''): return empty_response() rbstatus = None - try: - rbstatus = RebuilderdStatus.objects.get(pkg=pkg) - except RebuilderdStatus.DoesNotExist: - pass + if request.user.is_authenticated: + try: + rbstatus = RebuilderdStatus.objects.get(pkg=pkg) + except RebuilderdStatus.DoesNotExist: + pass return render(request, 'packages/details.html', {'pkg': pkg, 'rbstatus': rbstatus, 'notreproducible': rbstatus.status == RebuilderdStatus.BAD if rbstatus else False}) except Package.DoesNotExist: From f5dd012c1ee949e088285ac594e9db2bd23d7a2b Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Sat, 20 Jul 2024 16:54:10 +0200 Subject: [PATCH 5/5] main: switch details_link to a simple tag An inclusion_tag renders a template on every request, for the glibc page this meant calling Template.render() 7529 times(!) and loading ~ 5 seconds on my AMD Ryzen 7 5700X 8 Core. With this change we now do 3629 Template.render calls in 500 ms. --- main/templatetags/details_link.py | 6 ++++-- templates/packages/details_link.html | 1 - 2 files changed, 4 insertions(+), 3 deletions(-) delete mode 100644 templates/packages/details_link.html diff --git a/main/templatetags/details_link.py b/main/templatetags/details_link.py index af45100a..ea86608f 100644 --- a/main/templatetags/details_link.py +++ b/main/templatetags/details_link.py @@ -3,6 +3,7 @@ from django import template from django.conf import settings +from django.utils.html import format_html from main.templatetags import pgp from main.utils import gitlab_project_name_to_path @@ -18,9 +19,10 @@ def link_encode(url, query): return "%s?%s" % (url, data) -@register.inclusion_tag('packages/details_link.html') +@register.simple_tag def details_link(pkg): - return {'pkg': pkg} + link = '%s' + return format_html(link % (pkg.get_absolute_url(), pkg.pkgname, pkg.pkgname)) @register.simple_tag diff --git a/templates/packages/details_link.html b/templates/packages/details_link.html deleted file mode 100644 index 41983375..00000000 --- a/templates/packages/details_link.html +++ /dev/null @@ -1 +0,0 @@ -{{ pkg.pkgname }} \ No newline at end of file