CartController now uses BatchController memoisation
This commit is contained in:
parent
3717adb262
commit
3d635521eb
1 changed files with 13 additions and 56 deletions
|
@ -16,6 +16,7 @@ from registrasion.models import commerce
|
||||||
from registrasion.models import conditions
|
from registrasion.models import conditions
|
||||||
from registrasion.models import inventory
|
from registrasion.models import inventory
|
||||||
|
|
||||||
|
from.batch import BatchController
|
||||||
from .category import CategoryController
|
from .category import CategoryController
|
||||||
from .discount import DiscountController
|
from .discount import DiscountController
|
||||||
from .flag import FlagController
|
from .flag import FlagController
|
||||||
|
@ -34,10 +35,11 @@ def _modifies_cart(func):
|
||||||
def inner(self, *a, **k):
|
def inner(self, *a, **k):
|
||||||
self._fail_if_cart_is_not_active()
|
self._fail_if_cart_is_not_active()
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
with CartController.operations_batch(self.cart.user) as mark:
|
with BatchController.batch(self.cart.user):
|
||||||
mark.mark = True # Marker that we've modified the cart
|
# Mark the version of self in the batch cache as modified
|
||||||
|
memoised = self.for_user(self.cart.user)
|
||||||
|
memoised._modified_by_batch = True
|
||||||
return func(self, *a, **k)
|
return func(self, *a, **k)
|
||||||
|
|
||||||
return inner
|
return inner
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,6 +49,7 @@ class CartController(object):
|
||||||
self.cart = cart
|
self.cart = cart
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@BatchController.memoise
|
||||||
def for_user(cls, user):
|
def for_user(cls, user):
|
||||||
''' Returns the user's current cart, or creates a new cart
|
''' Returns the user's current cart, or creates a new cart
|
||||||
if there isn't one ready yet. '''
|
if there isn't one ready yet. '''
|
||||||
|
@ -64,59 +67,6 @@ class CartController(object):
|
||||||
)
|
)
|
||||||
return cls(existing)
|
return cls(existing)
|
||||||
|
|
||||||
# Marks the carts that are currently in batches
|
|
||||||
_FOR_USER = {}
|
|
||||||
_BATCH_COUNT = collections.defaultdict(int)
|
|
||||||
_MODIFIED_CARTS = set()
|
|
||||||
|
|
||||||
class _ModificationMarker(object):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
@contextlib.contextmanager
|
|
||||||
def operations_batch(cls, user):
|
|
||||||
''' Marks the boundary for a batch of operations on a user's cart.
|
|
||||||
|
|
||||||
These markers can be nested. Only on exiting the outermost marker will
|
|
||||||
a batch be ended.
|
|
||||||
|
|
||||||
When a batch is ended, discounts are recalculated, and the cart's
|
|
||||||
revision is increased.
|
|
||||||
'''
|
|
||||||
|
|
||||||
if user not in cls._FOR_USER:
|
|
||||||
_ctrl = cls.for_user(user)
|
|
||||||
cls._FOR_USER[user] = (_ctrl, _ctrl.cart.id)
|
|
||||||
|
|
||||||
ctrl, _id = cls._FOR_USER[user]
|
|
||||||
|
|
||||||
cls._BATCH_COUNT[_id] += 1
|
|
||||||
try:
|
|
||||||
success = False
|
|
||||||
|
|
||||||
marker = cls._ModificationMarker()
|
|
||||||
yield marker
|
|
||||||
|
|
||||||
if hasattr(marker, "mark"):
|
|
||||||
cls._MODIFIED_CARTS.add(_id)
|
|
||||||
|
|
||||||
success = True
|
|
||||||
finally:
|
|
||||||
|
|
||||||
cls._BATCH_COUNT[_id] -= 1
|
|
||||||
|
|
||||||
# Only end on the outermost batch marker, and only if
|
|
||||||
# it excited cleanly, and a modification occurred
|
|
||||||
modified = _id in cls._MODIFIED_CARTS
|
|
||||||
outermost = cls._BATCH_COUNT[_id] == 0
|
|
||||||
if modified and outermost and success:
|
|
||||||
ctrl._end_batch()
|
|
||||||
cls._MODIFIED_CARTS.remove(_id)
|
|
||||||
|
|
||||||
# Clear out the cache on the outermost operation
|
|
||||||
if outermost:
|
|
||||||
del cls._FOR_USER[user]
|
|
||||||
|
|
||||||
def _fail_if_cart_is_not_active(self):
|
def _fail_if_cart_is_not_active(self):
|
||||||
self.cart.refresh_from_db()
|
self.cart.refresh_from_db()
|
||||||
if self.cart.status != commerce.Cart.STATUS_ACTIVE:
|
if self.cart.status != commerce.Cart.STATUS_ACTIVE:
|
||||||
|
@ -144,6 +94,13 @@ class CartController(object):
|
||||||
self.cart.time_last_updated = timezone.now()
|
self.cart.time_last_updated = timezone.now()
|
||||||
self.cart.reservation_duration = max(reservations)
|
self.cart.reservation_duration = max(reservations)
|
||||||
|
|
||||||
|
|
||||||
|
def end_batch(self):
|
||||||
|
''' Calls ``_end_batch`` if a modification has been performed in the
|
||||||
|
previous batch. '''
|
||||||
|
if hasattr(self,'_modified_by_batch'):
|
||||||
|
self._end_batch()
|
||||||
|
|
||||||
def _end_batch(self):
|
def _end_batch(self):
|
||||||
''' Performs operations that occur occur at the end of a batch of
|
''' Performs operations that occur occur at the end of a batch of
|
||||||
product changes/voucher applications etc.
|
product changes/voucher applications etc.
|
||||||
|
|
Loading…
Reference in a new issue