mirror of
https://mau.dev/maunium/synapse.git
synced 2024-08-23 10:45:48 +00:00
Allow @cached-wrapped functions to have a prefill method for setting entries
This commit is contained in:
parent
4631b737fd
commit
e76d485e29
@ -48,24 +48,30 @@ def cached(max_entries=1000):
|
|||||||
|
|
||||||
The wrapped function has an additional member, a callable called
|
The wrapped function has an additional member, a callable called
|
||||||
"invalidate". This can be used to remove individual entries from the cache.
|
"invalidate". This can be used to remove individual entries from the cache.
|
||||||
|
|
||||||
|
The wrapped function has another additional callable, called "prefill",
|
||||||
|
which can be used to insert values into the cache specifically, without
|
||||||
|
calling the calculation function.
|
||||||
"""
|
"""
|
||||||
def wrap(orig):
|
def wrap(orig):
|
||||||
cache = {}
|
cache = {}
|
||||||
|
|
||||||
|
def prefill(key, value):
|
||||||
|
while len(cache) > max_entries:
|
||||||
|
# TODO(paul): This feels too biased. However, a random index
|
||||||
|
# would be a bit inefficient, walking the list of keys just
|
||||||
|
# to ignore most of them?
|
||||||
|
del cache[cache.keys()[0]]
|
||||||
|
|
||||||
|
cache[key] = value
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def wrapped(self, key):
|
def wrapped(self, key):
|
||||||
if key in cache:
|
if key in cache:
|
||||||
defer.returnValue(cache[key])
|
defer.returnValue(cache[key])
|
||||||
|
|
||||||
ret = yield orig(self, key)
|
ret = yield orig(self, key)
|
||||||
|
prefill(key, ret)
|
||||||
while len(cache) > max_entries:
|
|
||||||
# TODO(paul): This feels too biased. However, a random index
|
|
||||||
# would be a bit inefficient, walking the list of keys just
|
|
||||||
# to ignore most of them?
|
|
||||||
del cache[cache.keys()[0]]
|
|
||||||
|
|
||||||
cache[key] = ret;
|
|
||||||
defer.returnValue(ret)
|
defer.returnValue(ret)
|
||||||
|
|
||||||
def invalidate(key):
|
def invalidate(key):
|
||||||
@ -73,6 +79,7 @@ def cached(max_entries=1000):
|
|||||||
del cache[key]
|
del cache[key]
|
||||||
|
|
||||||
wrapped.invalidate = invalidate
|
wrapped.invalidate = invalidate
|
||||||
|
wrapped.prefill = prefill
|
||||||
return wrapped
|
return wrapped
|
||||||
|
|
||||||
return wrap
|
return wrap
|
||||||
|
@ -87,3 +87,17 @@ class CacheDecoratorTestCase(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertTrue(callcount[0] >= 14,
|
self.assertTrue(callcount[0] >= 14,
|
||||||
msg="Expected callcount >= 14, got %d" % (callcount[0]))
|
msg="Expected callcount >= 14, got %d" % (callcount[0]))
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
def test_prefill(self):
|
||||||
|
callcount = [0]
|
||||||
|
|
||||||
|
@cached()
|
||||||
|
def func(self, key):
|
||||||
|
callcount[0] += 1
|
||||||
|
return key
|
||||||
|
|
||||||
|
func.prefill("foo", 123)
|
||||||
|
|
||||||
|
self.assertEquals((yield func(self, "foo")), 123)
|
||||||
|
self.assertEquals(callcount[0], 0)
|
||||||
|
Loading…
Reference in New Issue
Block a user