Move quota cache from database to redis (#2010)

This commit is contained in:
Raphael Michel
2021-03-29 09:42:27 +02:00
committed by GitHub
parent a927b47b8b
commit d3748a6194
14 changed files with 148 additions and 164 deletions

View File

@@ -995,7 +995,6 @@ class EventFilterForm(FilterForm):
'date_from': 'order_from',
'date_to': 'order_to',
'live': 'live',
'sum_tickets_paid': 'sum_tickets_paid'
}
status = forms.ChoiceField(
label=_('Status'),

View File

@@ -81,8 +81,6 @@
</th>
<th>
{% trans "Paid tickets per quota" %}
<a href="?{% url_replace request 'ordering' '-sum_tickets_paid' %}"><i class="fa fa-caret-down"></i></a>
<a href="?{% url_replace request 'ordering' 'sum_tickets_paid' %}"><i class="fa fa-caret-up"></i></a>
</th>
<th>
{% trans "Status" %}

View File

@@ -1,6 +1,7 @@
{% load i18n %}
<div class="quotabox" data-toggle="tooltip_html" data-placement="top"
title="{% trans "Quota:" %} {{ q.name }}<br>{% blocktrans with date=q.cached_availability_time|date:"SHORT_DATETIME_FORMAT" %}Numbers as of {{ date }}{% endblocktrans %}{% if q.cached_avail.1 is not None %}<br>{% blocktrans with num=q.cached_avail.1 %}Currently available: {{ num }}{% endblocktrans %}{% endif %}">
<a class="quotabox" data-toggle="tooltip_html" data-placement="top"
title="{% trans "Quota:" %} {{ q.name }}{% if q.cached_avail.1 is not None %}<br>{% blocktrans with num=q.cached_avail.1 %}Currently available: {{ num }}{% endblocktrans %}{% endif %}"
href="{% url "control:event.items.quotas.show" event=q.event.slug organizer=q.event.organizer.slug quota=q.pk %}">
{% if q.size|default_if_none:"NONE" == "NONE" %}
<div class="progress">
</div>
@@ -13,4 +14,4 @@
<div class="numbers">
{{ q.cached_availability_paid_orders|default_if_none:"?" }} / {{ q.size|default_if_none:"∞" }}
</div>
</div>
</a>

View File

@@ -80,8 +80,6 @@
</th>
<th>
{% trans "Paid tickets per quota" %}
<a href="?{% url_replace request 'filter-ordering' '-sum_tickets_paid' %}"><i class="fa fa-caret-down"></i></a>
<a href="?{% url_replace request 'filter-ordering' 'sum_tickets_paid' %}"><i class="fa fa-caret-up"></i></a>
</th>
<th>
{% trans "Status" %}

View File

@@ -202,14 +202,10 @@ def quota_widgets(sender, subevent=None, lazy=False, **kwargs):
widgets = []
quotas = sender.quotas.filter(subevent=subevent)
quotas_to_compute = [
q for q in quotas
if not q.cache_is_hot(now() + timedelta(seconds=5))
]
qa = QuotaAvailability()
if quotas_to_compute:
qa.queue(*quotas_to_compute)
qa.compute()
if quotas:
qa.queue(*quotas)
qa.compute(allow_cache=True)
for q in quotas:
if not lazy:

View File

@@ -1,9 +1,7 @@
from django.conf import settings
from django.contrib import messages
from django.db import transaction
from django.db.models import (
F, IntegerField, Max, Min, OuterRef, Prefetch, Subquery, Sum,
)
from django.db.models import F, Max, Min, Prefetch
from django.db.models.functions import Coalesce, Greatest
from django.http import JsonResponse
from django.shortcuts import redirect
@@ -52,17 +50,7 @@ class EventList(PaginationMixin, ListView):
order_to=Coalesce('max_fromto', 'max_to', 'max_from', 'date_to', 'date_from'),
)
sum_tickets_paid = Quota.objects.filter(
event=OuterRef('pk'), subevent__isnull=True
).order_by().values('event').annotate(
s=Sum('cached_availability_paid_orders')
).values(
's'
)
qs = qs.annotate(
sum_tickets_paid=Subquery(sum_tickets_paid, output_field=IntegerField())
).prefetch_related(
qs = qs.prefetch_related(
Prefetch('quotas',
queryset=Quota.objects.filter(subevent__isnull=True).annotate(s=Coalesce(F('size'), 0)).order_by('-s'),
to_attr='first_quotas')
@@ -90,15 +78,12 @@ class EventList(PaginationMixin, ListView):
qa = QuotaAvailability(early_out=False)
for q in quotas:
if q.cached_availability_time is None or q.cached_availability_paid_orders is None:
qa.queue(q)
qa.queue(q)
qa.compute()
for q in quotas:
q.cached_avail = (
qa.results[q] if q in qa.results
else (q.cached_availability_state, q.cached_availability_number)
)
q.cached_avail = qa.results[q]
q.cached_availability_paid_orders = qa.count_paid_orders.get(qa, 0)
if q.size is not None:
q.percent_paid = min(
100,

View File

@@ -6,9 +6,7 @@ from dateutil.rrule import DAILY, MONTHLY, WEEKLY, YEARLY, rrule, rruleset
from django.contrib import messages
from django.core.files import File
from django.db import connections, transaction
from django.db.models import (
Count, F, IntegerField, OuterRef, Prefetch, Subquery, Sum,
)
from django.db.models import Count, F, Prefetch
from django.db.models.functions import Coalesce, TruncDate, TruncTime
from django.forms import inlineformset_factory
from django.http import Http404, HttpResponse, HttpResponseRedirect
@@ -57,20 +55,11 @@ class SubEventQueryMixin:
return self.request.GET
def get_queryset(self, list=False):
sum_tickets_paid = Quota.objects.filter(
subevent=OuterRef('pk')
).order_by().values('subevent').annotate(
s=Sum('cached_availability_paid_orders')
).values(
's'
)
qs = self.request.event.subevents
if list:
qs = qs.annotate(
sum_tickets_paid=Subquery(sum_tickets_paid, output_field=IntegerField())
).prefetch_related(
qs = qs.prefetch_related(
Prefetch('quotas',
queryset=Quota.objects.annotate(s=Coalesce(F('size'), 0)).order_by('-s'),
queryset=self.request.event.quotas.annotate(s=Coalesce(F('size'), 0)).order_by('-s'),
to_attr='first_quotas')
)
if self.filter_form.is_valid():
@@ -108,15 +97,12 @@ class SubEventList(EventPermissionRequiredMixin, PaginationMixin, SubEventQueryM
qa = QuotaAvailability(early_out=False)
for q in quotas:
if q.cached_availability_time is None or q.cached_availability_paid_orders is None:
qa.queue(q)
qa.queue(q)
qa.compute()
for q in quotas:
q.cached_avail = (
qa.results[q] if q in qa.results
else (q.cached_availability_state, q.cached_availability_number)
)
q.cached_avail = qa.results[q]
q.cached_availability_paid_orders = qa.count_paid_orders.get(qa, 0)
if q.size is not None:
q.percent_paid = min(
100,
@@ -1220,8 +1206,7 @@ class SubEventBulkEdit(SubEventQueryMixin, EventPermissionRequiredMixin, FormVie
).values(
'item_list', 'var_list',
*(f.name for f in Quota._meta.fields if f.name not in (
'id', 'event', 'items', 'variations', 'cached_availability_state', 'cached_availability_number',
'cached_availability_paid_orders', 'cached_availability_time', 'closed',
'id', 'event', 'items', 'variations', 'closed',
))
).order_by('subevent_id')