Add database-level uniqueness constraint for check-ins

We measured that this creates a ~10% performance loss on MySQL, but
believe that correctness is more important. Also, in case on concurrent
check-ins on MySQL with default transaction isolation level, this might
lead to Internal Server Errors on all but one check-ins, which is still
better than to show green.
This commit is contained in:
Raphael Michel
2019-03-04 18:51:52 +01:00
parent e70738ae0c
commit 68dbfedfdf
2 changed files with 30 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
# Generated by Django 2.1.5 on 2019-03-04 17:26
from django.db import migrations
from django.db.models import Count
def make_checkins_unique(apps, se):
Checkin = apps.get_model('pretixbase', 'Checkin')
for d in Checkin.objects.order_by().values('list_id', 'position_id').annotate(c=Count('id')).filter(c__gt=1):
for c in Checkin.objects.filter(list_id=d['list_id'], position_id=d['position_id'])[:d['c'] - 1]:
c.delete()
class Migration(migrations.Migration):
dependencies = [
('pretixbase', '0111_auto_20190219_0949'),
]
operations = [
migrations.RunPython(
make_checkins_unique, migrations.RunPython.noop,
),
migrations.AlterUniqueTogether(
name='checkin',
unique_together={('list', 'position')},
),
]

View File

@@ -167,6 +167,9 @@ class Checkin(models.Model):
'pretixbase.CheckinList', related_name='checkins', on_delete=models.PROTECT,
)
class Meta:
unique_together = (('list', 'position'),)
def __repr__(self):
return "<Checkin: pos {} on list '{}' at {}>".format(
self.position, self.list, self.datetime