Adds design for BatchController
This commit is contained in:
		
							parent
							
								
									162a1f23dd
								
							
						
					
					
						commit
						78a41970ea
					
				
					 2 changed files with 88 additions and 3 deletions
				
			
		
							
								
								
									
										85
									
								
								registrasion/controllers/batch.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								registrasion/controllers/batch.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,85 @@ | |||
| import contextlib | ||||
| import functools | ||||
| 
 | ||||
| 
 | ||||
| class BatchController(object): | ||||
|     ''' Batches are sets of operations where certain queries for users may be | ||||
|     repeated, but are also unlikely change within the boundaries of the batch. | ||||
| 
 | ||||
|     Batches are keyed per-user. You can mark the edge of the batch with the | ||||
|     ``batch`` context manager. If you nest calls to ``batch``, only the | ||||
|     outermost call will have the effect of ending the batch. | ||||
| 
 | ||||
|     Batches store results for functions wrapped with ``memoise``. These results | ||||
|     for the user are flushed at the end of the batch. | ||||
| 
 | ||||
|     If a return for a memoised function has a callable attribute called | ||||
|     ``end_batch``, that attribute will be called at the end of the batch. | ||||
| 
 | ||||
|     ''' | ||||
| 
 | ||||
|     _user_caches = {} | ||||
| 
 | ||||
|     @classmethod | ||||
|     @contextlib.contextmanager | ||||
|     def batch(cls, user): | ||||
|         ''' Marks the entry point for a batch for the given user. ''' | ||||
|         pass | ||||
|         # TODO: store nesting count *inside* the cache object. You know it | ||||
|         # makes sense. | ||||
| 
 | ||||
|     @classmethod | ||||
|     def memoise(cls, func): | ||||
|         ''' Decorator that stores the result of the stored function in the | ||||
|         user's results cache until the batch completes. | ||||
| 
 | ||||
|         Arguments: | ||||
|             func (callable(user, *a, **k)): The function whose results we want | ||||
|                 to store. ``user`` must be the first argument; this is used as | ||||
|                 the cache key. | ||||
| 
 | ||||
|         Returns: | ||||
|             callable(user, *a, **k): The memosing version of ``func``. | ||||
| 
 | ||||
|         ''' | ||||
| 
 | ||||
|         @functools.wraps(func) | ||||
|         def f(user, *a, **k): | ||||
| 
 | ||||
|             cache = cls.get_cache(user) | ||||
|             if func not in cache: | ||||
|                 cache[func] = func(user, *a, **k) | ||||
| 
 | ||||
|             return cache[func] | ||||
| 
 | ||||
|         return f | ||||
| 
 | ||||
|     @classmethod | ||||
|     def get_cache(cls, user): | ||||
|         if user not in cls._user_caches: | ||||
|             return {}  # Return blank cache here, we'll just discard :) | ||||
| 
 | ||||
|         return cls._user_caches[user] | ||||
| 
 | ||||
| 
 | ||||
| ''' | ||||
| TODO: memoise CartController.for_user | ||||
| TODO: memoise user_remainders (Product, Category) | ||||
| TODO: memoise _filtered_flags | ||||
| TODO: memoise FlagCounter.count() (doesn't take user, but it'll do for now) | ||||
| TODO: memoise _filtered_discounts | ||||
| 
 | ||||
| Tests: | ||||
| - Correct nesting behaviour | ||||
|  - do we get different cache objects every time we get a cache in non-batched | ||||
|    contexts? | ||||
|  - do we get the same cache object for nested caches? | ||||
|   - do we get different cache objects when we back out of a batch and enter a | ||||
|    new one | ||||
| - are cache clears independent for different users? | ||||
| - ``end_batch`` behaviour for CartController (use for_user *A LOT*) | ||||
|   - discounts not calculated until outermost batch point exits. | ||||
|   - Revision number shouldn't change until outermost batch point exits. | ||||
| - Make sure memoisation ONLY happens when we're in a batch. | ||||
| 
 | ||||
| ''' | ||||
|  | @ -50,7 +50,7 @@ class DiscountController(object): | |||
|         categories and products. The discounts also list the available quantity | ||||
|         for this user, not including products that are pending purchase. ''' | ||||
| 
 | ||||
|         filtered_clauses = cls._filtered_clauses(user, categories, products) | ||||
|         filtered_clauses = cls._filtered_clauses(user) | ||||
| 
 | ||||
|         # clauses that match provided categories | ||||
|         categories = set(categories) | ||||
|  | @ -103,8 +103,8 @@ class DiscountController(object): | |||
|         ''' | ||||
| 
 | ||||
|         Returns: | ||||
|             Sequence[discountbase]: All discounts that passed the filter | ||||
|             function. | ||||
|             Sequence[DiscountForProduct | DiscountForCategory]: All clauses | ||||
|             that passed the filter function. | ||||
| 
 | ||||
|         ''' | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Christopher Neugebauer
						Christopher Neugebauer