Changeset - 3d635521ebf6
[Not reviewed]
0 1 0
Christopher Neugebauer - 8 years ago 2016-05-01 04:56:51
chrisjrn@gmail.com
CartController now uses BatchController memoisation
1 file changed with 13 insertions and 56 deletions:
0 comments (0 inline, 0 general)
registrasion/controllers/cart.py
Show inline comments
...
 
@@ -16,6 +16,7 @@ from registrasion.models import commerce
 
from registrasion.models import conditions
 
from registrasion.models import inventory
 

	
 
from.batch import BatchController
 
from .category import CategoryController
 
from .discount import DiscountController
 
from .flag import FlagController
...
 
@@ -34,10 +35,11 @@ def _modifies_cart(func):
 
    def inner(self, *a, **k):
 
        self._fail_if_cart_is_not_active()
 
        with transaction.atomic():
 
            with CartController.operations_batch(self.cart.user) as mark:
 
                mark.mark = True  # Marker that we've modified the cart
 
            with BatchController.batch(self.cart.user):
 
                # 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 inner
 

	
 

	
...
 
@@ -47,6 +49,7 @@ class CartController(object):
 
        self.cart = cart
 

	
 
    @classmethod
 
    @BatchController.memoise
 
    def for_user(cls, user):
 
        ''' Returns the user's current cart, or creates a new cart
 
        if there isn't one ready yet. '''
...
 
@@ -64,59 +67,6 @@ class CartController(object):
 
            )
 
        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):
 
        self.cart.refresh_from_db()
 
        if self.cart.status != commerce.Cart.STATUS_ACTIVE:
...
 
@@ -144,6 +94,13 @@ class CartController(object):
 
        self.cart.time_last_updated = timezone.now()
 
        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):
 
        ''' Performs operations that occur occur at the end of a batch of
 
        product changes/voucher applications etc.
0 comments (0 inline, 0 general)