From db63e20708cacf59df10683f7c66ac584a0e0b9e Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Mon, 27 May 2019 10:09:29 +0200 Subject: [PATCH] Optimize refresh_quota_caches for less long-running queries --- src/pretix/base/services/quotas.py | 40 +++++++++++++++++------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/src/pretix/base/services/quotas.py b/src/pretix/base/services/quotas.py index badb198fbf..76dab041af 100644 --- a/src/pretix/base/services/quotas.py +++ b/src/pretix/base/services/quotas.py @@ -1,11 +1,11 @@ from datetime import timedelta -from django.db import models -from django.db.models import F, Max, OuterRef, Q, Subquery +from django.conf import settings +from django.db.models import Max, Q from django.dispatch import receiver from django.utils.timezone import now -from pretix.base.models import LogEntry, Quota +from pretix.base.models import Event, LogEntry from pretix.celery_app import app from ..signals import periodic_task @@ -18,19 +18,25 @@ def build_all_quota_caches(sender, **kwargs): @app.task def refresh_quota_caches(): - last_activity = LogEntry.objects.filter( - event=OuterRef('event_id'), + # Active events + active = LogEntry.objects.using(settings.DATABASE_REPLICA).filter( + datetime__gt=now() - timedelta(days=7) ).order_by().values('event').annotate( - m=Max('datetime') - ).values( - 'm' + last_activity=Max('datetime') ) - quotas = Quota.objects.annotate( - last_activity=Subquery(last_activity, output_field=models.DateTimeField()) - ).filter( - Q(cached_availability_time__isnull=True) | - Q(cached_availability_time__lt=F('last_activity')) | - Q(cached_availability_time__lt=now() - timedelta(hours=2), last_activity__gt=now() - timedelta(days=7)) - ).select_related('subevent') - for q in quotas: - q.availability() + for a in active: + try: + e = Event.objects.using(settings.DATABASE_REPLICA).get(pk=a['event']) + except Event.DoesNotExist: + continue + quotas = e.quotas.filter( + Q(cached_availability_time__isnull=True) | + Q(cached_availability_time__lt=a['last_activity']) | + Q(cached_availability_time__lt=now() - timedelta(hours=2)) + ).filter( + Q(subevent__isnull=True) | + Q(subevent__date_to__isnull=False, subevent__date_to__gte=now() - timedelta(days=14)) | + Q(subevent__date_from__gte=now() - timedelta(days=14)) + ) + for q in quotas: + q.availability()