Skip to content
Snippets Groups Projects
Commit 91cb4619 authored by Paul "LeoNerd" Evans's avatar Paul "LeoNerd" Evans
Browse files

Allow @cached-wrapped functions to have more or fewer than 1 argument; assert...

Allow @cached-wrapped functions to have more or fewer than 1 argument; assert on the total count of them though
parent 532ebc4a
No related branches found
No related tags found
No related merge requests found
......@@ -54,13 +54,12 @@ cache_counter = metrics.register_cache(
# TODO(paul):
# * more generic key management
# * consider other eviction strategies - LRU?
def cached(max_entries=1000):
def cached(max_entries=1000, num_args=1):
""" A method decorator that applies a memoizing cache around the function.
The function is presumed to take one additional argument, which is used as
the key for the cache. Cache hits are served directly from the cache;
The function is presumed to take zero or more arguments, which are used in
a tuple as the key for the cache. Hits are served directly from the cache;
misses use the function body to generate the value.
The wrapped function has an additional member, a callable called
......@@ -76,26 +75,41 @@ def cached(max_entries=1000):
caches_by_name[name] = cache
def prefill(key, value):
def prefill(*args): # because I can't *keyargs, value
keyargs = args[:-1]
value = args[-1]
if len(keyargs) != num_args:
raise ValueError("Expected a call to have %d arguments", num_args)
while len(cache) > max_entries:
cache.popitem(last=False)
cache[key] = value
cache[keyargs] = value
@functools.wraps(orig)
@defer.inlineCallbacks
def wrapped(self, key):
if key in cache:
def wrapped(self, *keyargs):
if len(keyargs) != num_args:
raise ValueError("Expected a call to have %d arguments", num_args)
if keyargs in cache:
cache_counter.inc_hits(name)
defer.returnValue(cache[key])
defer.returnValue(cache[keyargs])
cache_counter.inc_misses(name)
ret = yield orig(self, key)
prefill(key, ret)
ret = yield orig(self, *keyargs)
prefill_args = keyargs + (ret,)
prefill(*prefill_args)
defer.returnValue(ret)
def invalidate(key):
cache.pop(key, None)
def invalidate(*keyargs):
if len(keyargs) != num_args:
raise ValueError("Expected a call to have %d arguments", num_args)
cache.pop(keyargs, None)
wrapped.invalidate = invalidate
wrapped.prefill = prefill
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment