mirror of
https://github.com/pretix/pretix.git
synced 2026-05-05 15:14:04 +00:00
Fix performance issue in sendmail_run_rules cronjob
This commit is contained in:
@@ -42,6 +42,7 @@ from django.db.models.signals import post_save
|
|||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.urls import resolve, reverse
|
from django.urls import resolve, reverse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
from django.utils.timezone import now
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django_scopes import scope, scopes_disabled
|
from django_scopes import scope, scopes_disabled
|
||||||
|
|
||||||
@@ -134,6 +135,7 @@ def sendmail_run_rules(sender, **kwargs):
|
|||||||
with scopes_disabled():
|
with scopes_disabled():
|
||||||
mails = ScheduledMail.objects.all()
|
mails = ScheduledMail.objects.all()
|
||||||
|
|
||||||
|
unchanged = []
|
||||||
for m in mails.filter(Q(last_computed__isnull=True)
|
for m in mails.filter(Q(last_computed__isnull=True)
|
||||||
| Q(subevent__last_modified__gt=F('last_computed'))
|
| Q(subevent__last_modified__gt=F('last_computed'))
|
||||||
| Q(event__last_modified__gt=F('last_computed'))):
|
| Q(event__last_modified__gt=F('last_computed'))):
|
||||||
@@ -141,6 +143,17 @@ def sendmail_run_rules(sender, **kwargs):
|
|||||||
m.recompute()
|
m.recompute()
|
||||||
if m.computed_datetime != previous:
|
if m.computed_datetime != previous:
|
||||||
m.save(update_fields=['last_computed', 'computed_datetime'])
|
m.save(update_fields=['last_computed', 'computed_datetime'])
|
||||||
|
else:
|
||||||
|
unchanged.append(m.pk)
|
||||||
|
|
||||||
|
if unchanged:
|
||||||
|
# Theoretically, we don't need to write back the unchanged ones to the database… but that will cause us to
|
||||||
|
# recompute them on every run until eternity. So we want to set their last_computed date to something more
|
||||||
|
# recent... but not for all of them at once, in case it's millions, so we don't stress the database without
|
||||||
|
# cause
|
||||||
|
batch_size = max(connection.ops.bulk_batch_size(['id'], unchanged) - 2, 100)
|
||||||
|
for i in range(max(1, 5000 // batch_size)):
|
||||||
|
ScheduledMail.objects.filter(pk__in=unchanged[i * batch_size:batch_size]).update(last_computed=now())
|
||||||
|
|
||||||
mails.filter(
|
mails.filter(
|
||||||
state=ScheduledMail.STATE_SCHEDULED,
|
state=ScheduledMail.STATE_SCHEDULED,
|
||||||
|
|||||||
Reference in New Issue
Block a user