forked from CGM_Public/pretix_original
Moved locking out of the model layer
This commit is contained in:
@@ -1559,8 +1559,6 @@ class Order(Versionable):
|
|||||||
def _is_still_available(self):
|
def _is_still_available(self):
|
||||||
error_messages = {
|
error_messages = {
|
||||||
'unavailable': _('Some of the ordered products were no longer available.'),
|
'unavailable': _('Some of the ordered products were no longer available.'),
|
||||||
'busy': _('We were not able to process the request completely as the '
|
|
||||||
'server was too busy.'),
|
|
||||||
}
|
}
|
||||||
positions = list(self.positions.all().select_related(
|
positions = list(self.positions.all().select_related(
|
||||||
'item', 'variation'
|
'item', 'variation'
|
||||||
@@ -1570,31 +1568,26 @@ class Order(Versionable):
|
|||||||
))
|
))
|
||||||
quota_cache = {}
|
quota_cache = {}
|
||||||
try:
|
try:
|
||||||
with self.event.lock():
|
for i, op in enumerate(positions):
|
||||||
for i, op in enumerate(positions):
|
quotas = list(op.item.quotas.all()) if op.variation is None else list(op.variation.quotas.all())
|
||||||
quotas = list(op.item.quotas.all()) if op.variation is None else list(op.variation.quotas.all())
|
if len(quotas) == 0:
|
||||||
if len(quotas) == 0:
|
raise Quota.QuotaExceededException(error_messages['unavailable'])
|
||||||
raise Quota.QuotaExceededException(error_messages['unavailable'])
|
|
||||||
|
|
||||||
for quota in quotas:
|
for quota in quotas:
|
||||||
# Lock the quota, so no other thread is allowed to perform sales covered by this
|
# Lock the quota, so no other thread is allowed to perform sales covered by this
|
||||||
# quota while we're doing so.
|
# quota while we're doing so.
|
||||||
if quota.identity not in quota_cache:
|
if quota.identity not in quota_cache:
|
||||||
quota_cache[quota.identity] = quota
|
quota_cache[quota.identity] = quota
|
||||||
quota.cached_availability = quota.availability()[1]
|
quota.cached_availability = quota.availability()[1]
|
||||||
else:
|
else:
|
||||||
# Use cached version
|
# Use cached version
|
||||||
quota = quota_cache[quota.identity]
|
quota = quota_cache[quota.identity]
|
||||||
quota.cached_availability -= 1
|
quota.cached_availability -= 1
|
||||||
if quota.cached_availability < 0:
|
if quota.cached_availability < 0:
|
||||||
# This quota is sold out/currently unavailable, so do not sell this at all
|
# This quota is sold out/currently unavailable, so do not sell this at all
|
||||||
raise Quota.QuotaExceededException(error_messages['unavailable'])
|
raise Quota.QuotaExceededException(error_messages['unavailable'])
|
||||||
except Quota.QuotaExceededException as e:
|
except Quota.QuotaExceededException as e:
|
||||||
return str(e)
|
return str(e)
|
||||||
except EventLock.LockTimeoutException:
|
|
||||||
# Is raised when there are too many threads asking for quota locks and we were
|
|
||||||
# unaible to get one
|
|
||||||
return error_messages['busy']
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ def release_event(event):
|
|||||||
:raises EventLock.LockReleaseException: if we do not own the lock
|
:raises EventLock.LockReleaseException: if we do not own the lock
|
||||||
"""
|
"""
|
||||||
if not hasattr(event, '_lock') or not event._lock:
|
if not hasattr(event, '_lock') or not event._lock:
|
||||||
raise EventLock.LockReleaseException('')
|
raise EventLock.LockReleaseException('Lock is not owned by this thread')
|
||||||
if settings.HAS_REDIS:
|
if settings.HAS_REDIS:
|
||||||
return release_event_redis(event)
|
return release_event_redis(event)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ from django.utils.timezone import now
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.views.generic import DetailView, ListView, TemplateView, View
|
from django.views.generic import DetailView, ListView, TemplateView, View
|
||||||
|
|
||||||
from pretix.base.models import CachedFile, CachedTicket, Item, Order, Quota
|
from pretix.base.models import (
|
||||||
|
CachedFile, CachedTicket, EventLock, Item, Order, Quota,
|
||||||
|
)
|
||||||
from pretix.base.services.export import export
|
from pretix.base.services.export import export
|
||||||
from pretix.base.services.orders import mark_order_paid
|
from pretix.base.services.orders import mark_order_paid
|
||||||
from pretix.base.services.stats import order_overview
|
from pretix.base.services.stats import order_overview
|
||||||
@@ -247,12 +249,17 @@ class OrderExtend(OrderView):
|
|||||||
if oldvalue > now():
|
if oldvalue > now():
|
||||||
self.form.save()
|
self.form.save()
|
||||||
else:
|
else:
|
||||||
is_available = self.order._is_still_available()
|
try:
|
||||||
if is_available is True:
|
with self.order.event.lock():
|
||||||
self.form.save()
|
is_available = self.order._is_still_available()
|
||||||
messages.success(self.request, _('The payment term has been changed.'))
|
if is_available is True:
|
||||||
else:
|
self.form.save()
|
||||||
messages.error(self.request, is_available)
|
messages.success(self.request, _('The payment term has been changed.'))
|
||||||
|
else:
|
||||||
|
messages.error(self.request, is_available)
|
||||||
|
except EventLock.LockTimeoutException:
|
||||||
|
messages.error(self.request, _('We were not able to process the request completely as the '
|
||||||
|
'server was too busy.'))
|
||||||
return self._redirect_back()
|
return self._redirect_back()
|
||||||
else:
|
else:
|
||||||
return self.get(*args, **kwargs)
|
return self.get(*args, **kwargs)
|
||||||
|
|||||||
Reference in New Issue
Block a user