def test_two_cachedcalls_with_same_key_use_same_cache(self): fun = CB(retvalue='bar') cc1 = CachedCall('qix', fun) cc2 = CachedCall('qix', fun) self.assertEqual(cc1(), cc2()) self.assertEqual(1, fun.called)
def test_decorator(self): tocache = {'animals': 2} toadd = {'people': 3} decorator = lambda c: dict(c, **toadd) expected = dict(tocache, **toadd) fun = CB(retvalue=tocache) cc = CachedCall('key', fun, decorator=decorator) self.assertEquals(expected, cc()) # Now test cached. cc = CachedCall('key', fun, decorator=decorator) self.assertEquals(expected, cc()) self.assertEquals(1, fun.called)
def test_cache_stores_json_correctly(self): fun = CB(retvalue={'foo': ['bar']}) cc = CachedCall('key', fun) self.assertEquals(fun.retvalue, cc()) self.assertEquals(fun.retvalue, cc()) self.assertEquals(1, fun.called)
def test_force_returns_new_value(self): fun = CB(retvalue=1) cc = CachedCall('key', fun) cc() fun.retvalue = 2 self.assertEqual(2, cc.force())
def test_inprocess_cache_prevents_multiple_calls_multiple_fetch(self): fun = CB() cc = CachedCall('key', fun) self.assertEqual(fun.retvalue, cc()) cache.delete('key') self.assertEqual(fun.retvalue, cc()) self.assertEqual(1, fun.called)
def test_skip_decorator(self): def decorator(self): raise Exception fun = CB() cc = CachedCall('key', fun, decorator=decorator) self.assertEquals(fun.retvalue, cc(skip_decorator=True)) self.assertEquals(fun.retvalue, cc.force(skip_decorator=True))
def test_force_updates_cached_value(self): fun = CB(retvalue=1) cc = CachedCall('key', fun) cc() fun.retvalue = 2 cc.force() self.assertEqual(2, cc())
def test_second_call_returns_value_without_calling_underlying_function( self): fun = CB() cc = CachedCall('key', fun) cc() self.assertEquals(fun.retvalue, cc()) self.assertEquals(1, fun.called)
def test_many_multicall(self): f1, f2, f3, f4, f5, f6 = [ CachedCall('key_%s' % n, CB(retvalue=n)) for n in [1, 2, 3, 4, 5, 6] ] self.assertEquals([[1], [2, 3], [4, 5, 6]], CachedCall.many_multicall([f1], [f2, f3], [f4, f5, f6]))
def test_multicall_half_cached_returns_results(self): funs = [CB(retvalue=n) for n in [1, 2, 3, 4, 5]] calls = [CachedCall("key_%s" % e, fun) for e, fun in enumerate(funs)] # Uncached self.assertEquals([1, 2, 3], CachedCall.multicall(calls[:3])) # Half cached self.assertEquals([1, 2, 3, 4, 5], CachedCall.multicall(calls)) self.assertEquals([1] * len(funs), [fun.called for fun in funs])
def details_by_id(cls, quest_id): from drawquest.apps.quests.details_models import QuestDetails def inner_call(): return cls.all_objects.get(id=quest_id)._details() return CachedCall( 'quest:{}:details_v6'.format(quest_id), inner_call, 24 * 60 * 60, promoter=QuestDetails, )
def test_inprocess_cached_prevents_multiple_fetches_in_multicall(self): funs = [CB(retvalue=n) for n in [1, 2, 3, 4, 5]] calls = [CachedCall("key_%s" % e, fun) for e, fun in enumerate(funs)] # Uncached self.assertEquals([1, 2, 3], CachedCall.multicall(calls[:3])) # Remove some of the backing stores cache.delete('key_0') cache.delete('key_1') CachedCall.inprocess_cache.delete('key_2') # 1,2 in-process only, 3 in redis only, 4,5 uncached self.assertEquals([1, 2, 3, 4, 5], CachedCall.multicall(calls)) self.assertEquals([1] * len(funs), [fun.called for fun in funs])
def details_by_username(cls, username, promoter=None): from drawquest.apps.drawquest_auth.details_models import UserDetails if promoter is None: promoter = UserDetails def inner_call(): return cls.objects.get(username=username)._details() return CachedCall( 'dq:user:{}:details_v2'.format(username), inner_call, 30 * 24 * 60 * 60, promoter=promoter, )
def details_by_id(cls, comment_id, promoter=None): from drawquest.apps.quest_comments.details_models import QuestCommentDetails if promoter is None: promoter = QuestCommentDetails def inner_call(): return cls.all_objects.get(id=comment_id)._details() return CachedCall( 'quest_comment:{}:details_v15'.format(comment_id), inner_call, 24 * 60 * 60, promoter=promoter, )
def avatar_by_username(cls, username): return CachedCall( "avatar:%s:details_v1" % username, lambda: cls.objects.get(username=username)._avatar_details(), 24 * 60 * 60, )
def func(): return CachedCall("key", calc)
def details_by_id(cls, id, **kwargs): return CachedCall( "activity:%s:details_v2" % id, lambda: cls.objects.get(id=id)._details(), 30 * 24 * 60 * 60, )
def details_by_id(cls, id, **kwargs): return CachedCall( 'activity:{}:details_v3'.format(id), lambda: cls.objects.get(id=id)._details(), 10 * 24 * 60 * 60, )
def test_uncached_call_returns_jsonlike_result(self): fun = CB(retvalue={1: 'bar'}) cc = CachedCall('key', fun) self.assertEquals({'1': 'bar'}, cc()) self.assertEquals({'1': 'bar'}, cc.force())
def spotlighted_threads(): return [ ThreadPreview.get_from_spotlighted_thread(st) for st in SpotlightedThread.objects.all() ] def suggested_threads(): spotlighted_ids = SpotlightedThread.objects.all().values_list('comment_id', flat=True) nav = browse.Navigation(sort='hot', hot_sort_type='order_by_image_replies') ops = list(browse.get_front_comments(AnonymousUser(), nav)) ops = [op for op in ops if op.id not in spotlighted_ids] ops = ops[:300] return [ThreadPreview.get_from_comment(op) for op in ops] def generate_homepage(): threads = spotlighted_threads() ctx = { 'threads': threads, 'DOMAIN': settings.DOMAIN, } return render_jinja_to_string('logged_out_homepage/homepage.html', ctx) cached_homepage = CachedCall('cached_homepage', generate_homepage, 15 * 60)
def test_first_call_returns_value(self): fun = CB() cc = CachedCall('key', fun) self.assertEquals(fun.retvalue, cc()) self.assertEquals(1, fun.called)