Fixed localization and error reporting with exceptions thrown in celery

This commit is contained in:
Raphael Michel
2016-03-21 17:47:02 +01:00
parent 2d91319955
commit fde5fffd3c
4 changed files with 49 additions and 23 deletions

View File

@@ -342,3 +342,16 @@ def language(lng):
yield yield
finally: finally:
translation.activate(_lng) translation.activate(_lng)
class LazyLocaleException(Exception):
def __init__(self, msg, msgargs=None):
self.msg = msg
self.msgargs = msgargs
super().__init__(msg, msgargs)
def __str__(self):
if self.msgargs:
return ugettext(self.msg) % self.msgargs
else:
return ugettext(self.msg)

View File

@@ -1,18 +1,18 @@
from datetime import datetime, timedelta from datetime import datetime, timedelta
from django.conf import settings from django.conf import settings
from django.db import transaction
from django.db.models import Q from django.db.models import Q
from django.utils.timezone import now from django.utils.timezone import now
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from typing import List, Optional, Tuple from typing import List, Optional, Tuple
from pretix.base.i18n import LazyLocaleException
from pretix.base.models import ( from pretix.base.models import (
CartPosition, Event, EventLock, Item, ItemVariation, Quota, Voucher, CartPosition, Event, EventLock, Item, ItemVariation, Quota, Voucher,
) )
class CartError(Exception): class CartError(LazyLocaleException):
pass pass
@@ -168,7 +168,7 @@ def _add_items_to_cart(event: Event, items: List[Tuple[int, Optional[int], int]]
existing = CartPosition.objects.filter(Q(cart_id=cart_id) & Q(event=event)).count() existing = CartPosition.objects.filter(Q(cart_id=cart_id) & Q(event=event)).count()
if sum(i[2] for i in items) + existing > int(event.settings.max_items_per_order): if sum(i[2] for i in items) + existing > int(event.settings.max_items_per_order):
# TODO: i18n plurals # TODO: i18n plurals
raise CartError(error_messages['max_items'] % event.settings.max_items_per_order) raise CartError(error_messages['max_items'], (event.settings.max_items_per_order,))
expiry = now() + timedelta(minutes=event.settings.get('reservation_time', as_type=int)) expiry = now() + timedelta(minutes=event.settings.get('reservation_time', as_type=int))
_extend_existing(event, cart_id, expiry) _extend_existing(event, cart_id, expiry)
@@ -232,22 +232,28 @@ def remove_items_from_cart(event: int, items: List[Tuple[int, Optional[int], int
if settings.HAS_CELERY: if settings.HAS_CELERY:
from pretix.celery import app from pretix.celery import app
@app.task(bind=True, max_retries=5, default_retry_delay=2) @app.task(bind=True, max_retries=5, default_retry_delay=1)
def add_items_to_cart_task(self, event: int, items: List[Tuple[int, Optional[int], int]], cart_id: str, def add_items_to_cart_task(self, event: int, items: List[Tuple[int, Optional[int], int]], cart_id: str,
voucher: str=None): voucher: str=None):
event = Event.objects.get(id=event) event = Event.objects.get(id=event)
try: try:
_add_items_to_cart(event, items, cart_id, voucher) try:
except EventLock.LockTimeoutException: _add_items_to_cart(event, items, cart_id, voucher)
self.retry(exc=CartError(error_messages['busy'])) except EventLock.LockTimeoutException:
self.retry(exc=CartError(error_messages['busy']))
except CartError as e:
return e
@app.task(bind=True, max_retries=5, default_retry_delay=2) @app.task(bind=True, max_retries=5, default_retry_delay=1)
def remove_items_from_cart_task(self, event: int, items: List[Tuple[int, Optional[int], int]], cart_id: str): def remove_items_from_cart_task(self, event: int, items: List[Tuple[int, Optional[int], int]], cart_id: str):
event = Event.objects.get(id=event) event = Event.objects.get(id=event)
try: try:
_remove_items_from_cart(event, items, cart_id) try:
except EventLock.LockTimeoutException: _remove_items_from_cart(event, items, cart_id)
self.retry(exc=CartError(error_messages['busy'])) except EventLock.LockTimeoutException:
self.retry(exc=CartError(error_messages['busy']))
except CartError as e:
return e
add_items_to_cart.task = add_items_to_cart_task add_items_to_cart.task = add_items_to_cart_task
remove_items_from_cart.task = remove_items_from_cart_task remove_items_from_cart.task = remove_items_from_cart_task

View File

@@ -7,7 +7,9 @@ from django.utils.timezone import now
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from typing import List from typing import List
from pretix.base.i18n import LazyDate, LazyNumber, language from pretix.base.i18n import (
LazyDate, LazyLocaleException, LazyNumber, language,
)
from pretix.base.models import ( from pretix.base.models import (
CartPosition, Event, EventLock, Order, OrderPosition, Quota, User, CartPosition, Event, EventLock, Order, OrderPosition, Quota, User,
) )
@@ -29,7 +31,6 @@ error_messages = {
'the quantity you selected. Please see below for details.'), 'the quantity you selected. Please see below for details.'),
'price_changed': _('The price of some of the items in your cart has changed in the ' 'price_changed': _('The price of some of the items in your cart has changed in the '
'meantime. Please see below for details.'), 'meantime. Please see below for details.'),
'max_items': _("You cannot select more than %s items per order"),
'internal': _("An internal error occured, please try again."), 'internal': _("An internal error occured, please try again."),
'busy': _('We were not able to process your request completely as the ' 'busy': _('We were not able to process your request completely as the '
'server was too busy. Please try again.'), 'server was too busy. Please try again.'),
@@ -142,7 +143,7 @@ def cancel_order(order, user=None):
return order return order
class OrderError(Exception): class OrderError(LazyLocaleException):
pass pass
@@ -315,20 +316,26 @@ def perform_order(event: str, payment_provider: str, positions: List[str],
if settings.HAS_CELERY: if settings.HAS_CELERY:
from pretix.celery import app from pretix.celery import app
@app.task(bind=True, max_retries=5, default_retry_delay=2) @app.task(bind=True, max_retries=5, default_retry_delay=1)
def perform_order_task(self, event: str, payment_provider: str, positions: List[str], def perform_order_task(self, event: str, payment_provider: str, positions: List[str],
email: str=None, locale: str=None, address: int=None): email: str=None, locale: str=None, address: int=None):
try: try:
return _perform_order(event, payment_provider, positions, email, locale, address) try:
except EventLock.LockTimeoutException: return _perform_order(event, payment_provider, positions, email, locale, address)
self.retry(exc=OrderError(error_messages['busy'])) except EventLock.LockTimeoutException:
self.retry(exc=OrderError(error_messages['busy']))
except OrderError as e:
return e
@app.task(bind=True, max_retries=5, default_retry_delay=2) @app.task(bind=True, max_retries=5, default_retry_delay=1)
def cancel_order_task(self, order: int, user: int=None): def cancel_order_task(self, order: int, user: int=None):
try: try:
return cancel_order(order, user) try:
except EventLock.LockTimeoutException: return cancel_order(order, user)
self.retry(exc=OrderError(error_messages['busy'])) except EventLock.LockTimeoutException:
self.retry(exc=OrderError(error_messages['busy']))
except OrderError as e:
return e
perform_order.task = perform_order_task perform_order.task = perform_order_task
cancel_order.task = cancel_order_task cancel_order.task = cancel_order_task

View File

@@ -48,7 +48,7 @@ class AsyncAction:
'ready': res.ready() 'ready': res.ready()
} }
if res.ready(): if res.ready():
if res.successful(): if res.successful() and not isinstance(res.info, Exception):
smes = self.get_success_message(res.info) smes = self.get_success_message(res.info)
if smes: if smes:
messages.success(self.request, smes) messages.success(self.request, smes)