Move ticket cache invalidation to background task

This commit is contained in:
Raphael Michel
2019-04-18 09:17:01 +02:00
parent b3684377cd
commit 9ad4607d26
9 changed files with 57 additions and 52 deletions

View File

@@ -32,6 +32,7 @@ from pretix.base.models import (
generate_position_secret, generate_secret, generate_position_secret, generate_secret,
) )
from pretix.base.payment import PaymentException from pretix.base.payment import PaymentException
from pretix.base.services import tickets
from pretix.base.services.invoices import ( from pretix.base.services.invoices import (
generate_cancellation, generate_invoice, invoice_pdf, invoice_qualified, generate_cancellation, generate_invoice, invoice_pdf, invoice_qualified,
regenerate_invoice, regenerate_invoice,
@@ -370,6 +371,8 @@ class OrderViewSet(viewsets.ModelViewSet):
order.save(update_fields=['secret']) order.save(update_fields=['secret'])
CachedTicket.objects.filter(order_position__order=order).delete() CachedTicket.objects.filter(order_position__order=order).delete()
CachedCombinedTicket.objects.filter(order=order).delete() CachedCombinedTicket.objects.filter(order=order).delete()
tickets.invalidate_cache.apply_async(kwargs={'event': self.request.event.pk,
'order': order.pk})
order.log_action( order.log_action(
'pretix.event.order.secret.changed', 'pretix.event.order.secret.changed',
user=self.request.user, user=self.request.user,

View File

@@ -28,12 +28,13 @@ from pretix.base.models import (
from pretix.base.models.event import SubEvent from pretix.base.models.event import SubEvent
from pretix.base.models.items import ItemBundle from pretix.base.models.items import ItemBundle
from pretix.base.models.orders import ( from pretix.base.models.orders import (
CachedCombinedTicket, CachedTicket, InvoiceAddress, OrderFee, OrderRefund, InvoiceAddress, OrderFee, OrderRefund, generate_position_secret,
generate_position_secret, generate_secret, generate_secret,
) )
from pretix.base.models.organizer import TeamAPIToken from pretix.base.models.organizer import TeamAPIToken
from pretix.base.models.tax import TaxedPrice from pretix.base.models.tax import TaxedPrice
from pretix.base.payment import BasePaymentProvider, PaymentException from pretix.base.payment import BasePaymentProvider, PaymentException
from pretix.base.services import tickets
from pretix.base.services.invoices import ( from pretix.base.services.invoices import (
generate_cancellation, generate_invoice, invoice_qualified, generate_cancellation, generate_invoice, invoice_qualified,
) )
@@ -857,6 +858,7 @@ class OrderChangeManager:
self.order = order self.order = order
self.user = user self.user = user
self.auth = auth self.auth = auth
self.event = order.event
self.split_order = None self.split_order = None
self._committed = False self._committed = False
self._totaldiff = 0 self._totaldiff = 0
@@ -1159,8 +1161,8 @@ class OrderChangeManager:
elif isinstance(op, self.RegenerateSecretOperation): elif isinstance(op, self.RegenerateSecretOperation):
op.position.secret = generate_position_secret() op.position.secret = generate_position_secret()
op.position.save() op.position.save()
CachedTicket.objects.filter(order_position__order=self.order).delete() tickets.invalidate_cache.apply_async(kwargs={'event': self.event.pk,
CachedCombinedTicket.objects.filter(order=self.order).delete() 'order': self.order.pk})
self.order.log_action('pretix.event.order.changed.secret', user=self.user, auth=self.auth, data={ self.order.log_action('pretix.event.order.changed.secret', user=self.user, auth=self.auth, data={
'position': op.position.pk, 'position': op.position.pk,
'positionid': op.position.positionid, 'positionid': op.position.positionid,
@@ -1393,11 +1395,11 @@ class OrderChangeManager:
order_changed.send(self.order.event, order=self.order) order_changed.send(self.order.event, order=self.order)
def _clear_tickets_cache(self): def _clear_tickets_cache(self):
CachedTicket.objects.filter(order_position__order=self.order).delete() tickets.invalidate_cache.apply_async(kwargs={'event': self.event.pk,
CachedCombinedTicket.objects.filter(order=self.order).delete() 'order': self.order.pk})
if self.split_order: if self.split_order:
CachedTicket.objects.filter(order_position__order=self.split_order).delete() tickets.invalidate_cache.apply_async(kwargs={'event': self.event.pk,
CachedCombinedTicket.objects.filter(order=self.split_order).delete() 'order': self.split_order.pk})
def _get_payment_provider(self): def _get_payment_provider(self):
lp = self.order.payments.last() lp = self.order.payments.last()

View File

@@ -156,3 +156,26 @@ def get_tickets_for_order(order):
logger.exception('Failed to generate ticket.') logger.exception('Failed to generate ticket.')
return tickets return tickets
@app.task(base=ProfiledTask)
def invalidate_cache(event: int, item: int=None, provider: str=None, order: int=None, **kwargs):
event = Event.objects.get(id=event)
qs = CachedTicket.objects.filter(order_position__order__event=event)
qsc = CachedCombinedTicket.objects.filter(order__event=event)
if item:
qs = qs.filter(order_position__item_id=item)
if provider:
qs = qs.filter(provider=provider)
qsc = qsc.filter(provider=provider)
if order:
qs = qs.filter(order_position__order_id=order)
qsc = qsc.filter(order_id=Order)
for ct in qs:
ct.delete()
for ct in qsc:
ct.delete()

View File

@@ -31,8 +31,7 @@ from pytz import timezone
from pretix.base.channels import get_all_sales_channels from pretix.base.channels import get_all_sales_channels
from pretix.base.i18n import LazyCurrencyNumber from pretix.base.i18n import LazyCurrencyNumber
from pretix.base.models import ( from pretix.base.models import (
CachedCombinedTicket, CachedTicket, Event, LogEntry, Order, RequiredAction, Event, LogEntry, Order, RequiredAction, TaxRule, Voucher,
TaxRule, Voucher,
) )
from pretix.base.models.event import EventMetaValue from pretix.base.models.event import EventMetaValue
from pretix.base.services import tickets from pretix.base.services import tickets
@@ -789,12 +788,7 @@ class TicketSettings(EventSettingsViewMixin, EventPermissionRequiredMixin, FormV
for k in provider.form.changed_data for k in provider.form.changed_data
} }
) )
CachedTicket.objects.filter( tickets.invalidate_cache.apply_async(kwargs={'event': self.request.event.pk, 'provider': provider.identifier})
order_position__order__event=self.request.event, provider=provider.identifier
).delete()
CachedCombinedTicket.objects.filter(
order__event=self.request.event, provider=provider.identifier
).delete()
else: else:
success = False success = False
form = self.get_form(self.get_form_class()) form = self.get_form(self.get_form_class())

View File

@@ -18,11 +18,12 @@ from django.views.generic.edit import DeleteView
from pretix.base.forms import I18nFormSet from pretix.base.forms import I18nFormSet
from pretix.base.models import ( from pretix.base.models import (
CachedTicket, CartPosition, Item, ItemCategory, ItemVariation, Order, CartPosition, Item, ItemCategory, ItemVariation, Order, Question,
Question, QuestionAnswer, QuestionOption, Quota, Voucher, QuestionAnswer, QuestionOption, Quota, Voucher,
) )
from pretix.base.models.event import SubEvent from pretix.base.models.event import SubEvent
from pretix.base.models.items import ItemAddOn, ItemBundle from pretix.base.models.items import ItemAddOn, ItemBundle
from pretix.base.services.tickets import invalidate_cache
from pretix.control.forms.item import ( from pretix.control.forms.item import (
CategoryForm, ItemAddOnForm, ItemAddOnsFormSet, ItemBundleForm, CategoryForm, ItemAddOnForm, ItemAddOnsFormSet, ItemBundleForm,
ItemBundleFormSet, ItemCreateForm, ItemUpdateForm, ItemVariationForm, ItemBundleFormSet, ItemCreateForm, ItemUpdateForm, ItemVariationForm,
@@ -875,7 +876,7 @@ class ItemUpdateGeneral(ItemDetailMixin, EventPermissionRequiredMixin, UpdateVie
self.object.log_action( self.object.log_action(
'pretix.event.item.changed', user=self.request.user, data=data 'pretix.event.item.changed', user=self.request.user, data=data
) )
CachedTicket.objects.filter(order_position__item=self.item).delete() invalidate_cache.apply_async(kwargs={'event': self.request.event.pk, 'item': self.object.pk})
for f in self.plugin_forms: for f in self.plugin_forms:
f.save() f.save()
return super().form_valid(form) return super().form_valid(form)

View File

@@ -43,6 +43,7 @@ from pretix.base.models.orders import (
) )
from pretix.base.models.tax import EU_COUNTRIES from pretix.base.models.tax import EU_COUNTRIES
from pretix.base.payment import PaymentException from pretix.base.payment import PaymentException
from pretix.base.services import tickets
from pretix.base.services.export import export from pretix.base.services.export import export
from pretix.base.services.invoices import ( from pretix.base.services.invoices import (
generate_cancellation, generate_invoice, invoice_pdf, invoice_pdf_task, generate_cancellation, generate_invoice, invoice_pdf, invoice_pdf_task,
@@ -1319,8 +1320,7 @@ class OrderModifyInformation(OrderQuestionsViewMixin, OrderView):
'you need to do this manually.') 'you need to do this manually.')
messages.success(self.request, _(success_message)) messages.success(self.request, _(success_message))
CachedTicket.objects.filter(order_position__order=self.order).delete() tickets.invalidate_cache.apply_async(kwargs={'event': self.request.event.pk, 'order': self.order.pk})
CachedCombinedTicket.objects.filter(order=self.order).delete()
order_modified.send(sender=self.request.event, order=self.order) order_modified.send(sender=self.request.event, order=self.order)
return redirect(self.get_order_url()) return redirect(self.get_order_url())
@@ -1363,8 +1363,7 @@ class OrderContactChange(OrderView):
for op in self.order.all_positions.all(): for op in self.order.all_positions.all():
op.secret = generate_position_secret() op.secret = generate_position_secret()
op.save() op.save()
CachedTicket.objects.filter(order_position__order=self.order).delete() tickets.invalidate_cache.apply_async(kwargs={'event': self.request.event.pk, 'order': self.order.pk})
CachedCombinedTicket.objects.filter(order=self.order).delete()
self.order.log_action('pretix.event.order.secret.changed', user=self.request.user) self.order.log_action('pretix.event.order.secret.changed', user=self.request.user)
self.form.save() self.form.save()

View File

@@ -1,7 +1,7 @@
from django import forms from django import forms
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from pretix.base.models import CachedCombinedTicket, CachedTicket from pretix.base.services import tickets
from .models import TicketLayout, TicketLayoutItem from .models import TicketLayout, TicketLayoutItem
@@ -18,7 +18,7 @@ class TicketLayoutItemForm(forms.ModelForm):
fields = ('layout',) fields = ('layout',)
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
event = kwargs.pop('event') self.event = kwargs.pop('event')
self.sales_channel = kwargs.pop('sales_channel') self.sales_channel = kwargs.pop('sales_channel')
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
if self.sales_channel.identifier != 'web': if self.sales_channel.identifier != 'web':
@@ -29,7 +29,7 @@ class TicketLayoutItemForm(forms.ModelForm):
else: else:
self.fields['layout'].label = _('PDF ticket layout') self.fields['layout'].label = _('PDF ticket layout')
self.fields['layout'].empty_label = _('(Event default)') self.fields['layout'].empty_label = _('(Event default)')
self.fields['layout'].queryset = event.ticket_layouts.all() self.fields['layout'].queryset = self.event.ticket_layouts.all()
self.fields['layout'].required = False self.fields['layout'].required = False
def save(self, commit=True): def save(self, commit=True):
@@ -41,9 +41,5 @@ class TicketLayoutItemForm(forms.ModelForm):
return return
else: else:
return super().save(commit=commit) return super().save(commit=commit)
CachedTicket.objects.filter( tickets.invalidate_cache.apply_async(kwargs={'event': self.event.pk, 'provider': 'pdf',
order_position__item_id=self.instance.item, provider='pdf' 'item': self.instance.item_id})
).delete()
CachedCombinedTicket.objects.filter(
order__all_positions__item=self.instance.item
).delete()

View File

@@ -18,10 +18,9 @@ from django.views.generic import CreateView, DeleteView, DetailView, ListView
from reportlab.lib import pagesizes from reportlab.lib import pagesizes
from reportlab.pdfgen import canvas from reportlab.pdfgen import canvas
from pretix.base.models import ( from pretix.base.models import CachedFile, OrderPosition
CachedCombinedTicket, CachedFile, CachedTicket, OrderPosition,
)
from pretix.base.pdf import Renderer from pretix.base.pdf import Renderer
from pretix.base.services.tickets import invalidate_cache
from pretix.control.permissions import EventPermissionRequiredMixin from pretix.control.permissions import EventPermissionRequiredMixin
from pretix.control.views.pdf import BaseEditorView from pretix.control.views.pdf import BaseEditorView
from pretix.plugins.ticketoutputpdf.forms import TicketLayoutForm from pretix.plugins.ticketoutputpdf.forms import TicketLayoutForm
@@ -40,12 +39,7 @@ class EditorView(BaseEditorView):
def save_layout(self): def save_layout(self):
super().save_layout() super().save_layout()
CachedTicket.objects.filter( invalidate_cache.apply_async(kwargs={'event': self.request.event.pk, 'provider': 'pdf'})
order_position__order__event=self.request.event, provider='pdf'
).delete()
CachedCombinedTicket.objects.filter(
order__event=self.request.event, provider='pdf'
).delete()
def get_layout_settings_key(self): def get_layout_settings_key(self):
return 'ticketoutput_pdf_layout' return 'ticketoutput_pdf_layout'
@@ -212,10 +206,7 @@ class LayoutEditorView(BaseEditorView):
self.layout.save(update_fields=['layout']) self.layout.save(update_fields=['layout'])
self.layout.log_action(action='pretix.plugins.ticketoutputpdf.layout.changed', user=self.request.user, self.layout.log_action(action='pretix.plugins.ticketoutputpdf.layout.changed', user=self.request.user,
data={'layout': self.request.POST.get("data")}) data={'layout': self.request.POST.get("data")})
for ct in CachedTicket.objects.filter(order_position__order__event=self.request.event, provider='pdf'): invalidate_cache.apply_async(kwargs={'event': self.request.event.pk, 'provider': 'pdf'})
ct.delete()
for ct in CachedCombinedTicket.objects.filter(order__event=self.request.event, provider='pdf'):
ct.delete()
def get_default_background(self): def get_default_background(self):
return static('pretixpresale/pdf/ticket_default_a4.pdf') return static('pretixpresale/pdf/ticket_default_a4.pdf')
@@ -251,9 +242,4 @@ class LayoutEditorView(BaseEditorView):
if self.layout.background: if self.layout.background:
self.layout.background.delete() self.layout.background.delete()
self.layout.background.save('background.pdf', f.file) self.layout.background.save('background.pdf', f.file)
CachedTicket.objects.filter( invalidate_cache.apply_async(kwargs={'event': self.request.event.pk, 'provider': 'pdf'})
order_position__order__event=self.request.event, provider='pdf'
).delete()
CachedCombinedTicket.objects.filter(
order__event=self.request.event, provider='pdf'
).delete()

View File

@@ -29,7 +29,7 @@ from pretix.base.services.invoices import (
) )
from pretix.base.services.mail import SendMailException from pretix.base.services.mail import SendMailException
from pretix.base.services.orders import cancel_order, change_payment_provider from pretix.base.services.orders import cancel_order, change_payment_provider
from pretix.base.services.tickets import generate from pretix.base.services.tickets import generate, invalidate_cache
from pretix.base.signals import ( from pretix.base.signals import (
allow_ticket_download, order_modified, register_ticket_outputs, allow_ticket_download, order_modified, register_ticket_outputs,
) )
@@ -548,6 +548,7 @@ class OrderModify(EventViewMixin, OrderDetailMixin, OrderQuestionsViewMixin, Tem
'to regenerate your invoice.') 'to regenerate your invoice.')
messages.success(self.request, _(success_message)) messages.success(self.request, _(success_message))
invalidate_cache.apply_async(kwargs={'event': self.request.event.pk, 'order': self.order.pk})
CachedTicket.objects.filter(order_position__order=self.order).delete() CachedTicket.objects.filter(order_position__order=self.order).delete()
CachedCombinedTicket.objects.filter(order=self.order).delete() CachedCombinedTicket.objects.filter(order=self.order).delete()
return redirect(self.get_order_url()) return redirect(self.get_order_url())