diff options
-rw-r--r-- | synapse/util/caches/lrucache.py | 22 | ||||
-rw-r--r-- | tests/util/test_lrucache.py | 17 |
2 files changed, 32 insertions, 7 deletions
diff --git a/synapse/util/caches/lrucache.py b/synapse/util/caches/lrucache.py index e0749ac8a2..b2af081e02 100644 --- a/synapse/util/caches/lrucache.py +++ b/synapse/util/caches/lrucache.py @@ -34,7 +34,6 @@ from typing_extensions import Literal from synapse.config import cache as cache_config from synapse.util.caches import CacheMetric, register_cache from synapse.util.caches.treecache import TreeCache -from twisted.internet import reactor try: from pympler import asizeof @@ -72,7 +71,7 @@ class _Node: "allocated_ts", ] - def __init__(self, prev_node, next_node, key, value, callbacks=set()): + def __init__(self, prev_node, next_node, key, value, allocated_ts, callbacks=set()): self.key = key self.value = value self.callbacks = callbacks @@ -88,7 +87,7 @@ class _Node: self.prev_node = prev_node self.next_node = next_node - self.allocated_ts = int(reactor.seconds()) + random.randint(-60, 60) + self.allocated_ts = allocated_ts class LruCache(Generic[KT, VT]): @@ -108,6 +107,7 @@ class LruCache(Generic[KT, VT]): size_callback: Optional[Callable] = None, metrics_collection_callback: Optional[Callable[[], None]] = None, apply_cache_factor_from_config: bool = True, + reactor=None, ): """ Args: @@ -136,6 +136,11 @@ class LruCache(Generic[KT, VT]): apply_cache_factor_from_config (bool): If true, `max_size` will be multiplied by a cache factor derived from the homeserver config """ + if reactor is None: + from twisted.internet import reactor as _reactor + + reactor = _reactor + cache = cache_type() self.cache = cache # Used for introspection. self.apply_cache_factor_from_config = apply_cache_factor_from_config @@ -167,10 +172,9 @@ class LruCache(Generic[KT, VT]): # this is exposed for access from outside this class self.metrics = metrics - list_root = _Node(None, None, None, None) + list_root = _Node(None, None, None, None, -1) list_root.next_node = list_root list_root.prev_node = list_root - list_root.allocated_ts = -1 lock = threading.Lock() @@ -188,7 +192,7 @@ class LruCache(Generic[KT, VT]): if list_root == todelete: break - if 0 < todelete.allocated_ts < ten_minutes_ago: + if ten_minutes_ago < todelete.allocated_ts: todelete = todelete.prev_node continue @@ -225,7 +229,11 @@ class LruCache(Generic[KT, VT]): def add_node(key, value, callbacks=set()): prev_node = list_root next_node = prev_node.next_node - node = _Node(prev_node, next_node, key, value, callbacks) + + ts = int(reactor.seconds()) + random.randint(-60, 60) + print("Allocating at", ts) + + node = _Node(prev_node, next_node, key, value, ts, callbacks) prev_node.next_node = node next_node.prev_node = node cache[key] = node diff --git a/tests/util/test_lrucache.py b/tests/util/test_lrucache.py index a739a6aaaf..dd8c46ee49 100644 --- a/tests/util/test_lrucache.py +++ b/tests/util/test_lrucache.py @@ -30,6 +30,23 @@ class LruCacheTestCase(unittest.HomeserverTestCase): self.assertEquals(cache.get("key"), "value") self.assertEquals(cache["key"], "value") + def test_time_evict(self): + self.reactor.advance(100 * 60) + + cache = LruCache(100, reactor=self.reactor) + cache["key"] = "value" + cache["key2"] = "value2" + + cache._on_resize() + self.assertEquals(cache.get("key"), "value") + + self.reactor.advance(20 * 60) + + print(self.reactor.seconds()) + + cache._on_resize() + self.assertEquals(cache.get("key"), None) + def test_eviction(self): cache = LruCache(2) cache[1] = 1 |