diff --git a/synapse/storage/_base.py b/synapse/storage/_base.py
index be9934c66f..fd275039be 100644
--- a/synapse/storage/_base.py
+++ b/synapse/storage/_base.py
@@ -35,6 +35,41 @@ sql_logger = logging.getLogger("synapse.storage.SQL")
transaction_logger = logging.getLogger("synapse.storage.txn")
+# TODO(paul):
+# * Move this somewhere higher-level, shared;
+# * more generic key management
+# * export monitoring stats
+# * maximum size; just evict things at random, or consider LRU?
+def cached(orig):
+ """ 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;
+ misses use the function body to generate the value.
+
+ The wrapped function has an additional member, a callable called
+ "invalidate". This can be used to remove individual entries from the cache.
+ """
+ cache = {}
+
+ @defer.inlineCallbacks
+ def wrapped(self, key):
+ if key in cache:
+ defer.returnValue(cache[key])
+
+ ret = yield orig(self, key)
+
+ cache[key] = ret;
+ defer.returnValue(ret)
+
+ def invalidate(key):
+ if key in cache:
+ del cache[key]
+
+ wrapped.invalidate = invalidate
+ return wrapped
+
+
class LoggingTransaction(object):
"""An object that almost-transparently proxies for the 'txn' object
passed to the constructor. Adds logging to the .execute() method."""
diff --git a/synapse/storage/roommember.py b/synapse/storage/roommember.py
index 569bd55d0f..b8fcc1927e 100644
--- a/synapse/storage/roommember.py
+++ b/synapse/storage/roommember.py
@@ -17,7 +17,7 @@ from twisted.internet import defer
from collections import namedtuple
-from ._base import SQLBaseStore
+from ._base import SQLBaseStore, cached
from synapse.api.constants import Membership
from synapse.types import UserID
@@ -33,32 +33,6 @@ RoomsForUser = namedtuple(
)
-# TODO(paul):
-# * Move this somewhere higher-level, shared;
-# * more generic key management
-# * export monitoring stats
-# * maximum size; just evict things at random, or consider LRU?
-def cached(orig):
- cache = {}
-
- @defer.inlineCallbacks
- def wrapped(self, key):
- if key in cache:
- defer.returnValue(cache[key])
-
- ret = yield orig(self, key)
-
- cache[key] = ret;
- defer.returnValue(ret)
-
- def invalidate(key):
- if key in cache:
- del cache[key]
-
- wrapped.invalidate = invalidate
- return wrapped
-
-
class RoomMemberStore(SQLBaseStore):
def __init__(self, *args, **kw):
|