summary refs log tree commit diff
path: root/synapse
diff options
context:
space:
mode:
authorErik Johnston <erik@matrix.org>2015-08-06 13:33:34 +0100
committerErik Johnston <erik@matrix.org>2015-08-06 13:33:34 +0100
commit7eea3e356ff58168f3525879a8eb684f0681ee68 (patch)
tree1b358647cced4da2e17e631715bbc85c5f39e735 /synapse
parentAdd support for using keyword arguments with cached functions (diff)
downloadsynapse-7eea3e356ff58168f3525879a8eb684f0681ee68.tar.xz
Make @cached cache deferreds rather than the deferreds' values
Diffstat (limited to 'synapse')
-rw-r--r--synapse/storage/_base.py21
-rw-r--r--synapse/util/async.py9
2 files changed, 15 insertions, 15 deletions
diff --git a/synapse/storage/_base.py b/synapse/storage/_base.py
index f1265541ba..8604d38c3e 100644
--- a/synapse/storage/_base.py
+++ b/synapse/storage/_base.py
@@ -15,6 +15,7 @@
 import logging
 
 from synapse.api.errors import StoreError
+from synapse.util.async import ObservableDeferred
 from synapse.util.logutils import log_function
 from synapse.util.logcontext import preserve_context_over_fn, LoggingContext
 from synapse.util.lrucache import LruCache
@@ -173,33 +174,27 @@ class CacheDescriptor(object):
         )
 
         @functools.wraps(self.orig)
-        @defer.inlineCallbacks
         def wrapped(*args, **kwargs):
             arg_dict = inspect.getcallargs(self.orig, obj, *args, **kwargs)
             keyargs = [arg_dict[arg_nm] for arg_nm in self.arg_names]
             try:
                 cached_result = cache.get(*keyargs)
-                if DEBUG_CACHES:
-                    actual_result = yield self.function_to_call(obj, *args, **kwargs)
-                    if actual_result != cached_result:
-                        logger.error(
-                            "Stale cache entry %s%r: cached: %r, actual %r",
-                            self.orig.__name__, keyargs,
-                            cached_result, actual_result,
-                        )
-                        raise ValueError("Stale cache entry")
-                defer.returnValue(cached_result)
+                return cached_result.observe()
             except KeyError:
                 # Get the sequence number of the cache before reading from the
                 # database so that we can tell if the cache is invalidated
                 # while the SELECT is executing (SYN-369)
                 sequence = cache.sequence
 
-                ret = yield self.function_to_call(obj, *args, **kwargs)
+                ret = defer.maybeDeferred(
+                    self.function_to_call,
+                    obj, *args, **kwargs
+                )
+                ret = ObservableDeferred(ret, consumeErrors=False)
 
                 cache.update(sequence, *(keyargs + [ret]))
 
-                defer.returnValue(ret)
+                return ret.observe()
 
         wrapped.invalidate = cache.invalidate
         wrapped.invalidate_all = cache.invalidate_all
diff --git a/synapse/util/async.py b/synapse/util/async.py
index 5a1d545c96..7bf2d38bb8 100644
--- a/synapse/util/async.py
+++ b/synapse/util/async.py
@@ -51,7 +51,7 @@ class ObservableDeferred(object):
         object.__setattr__(self, "_observers", set())
 
         def callback(r):
-            self._result = (True, r)
+            object.__setattr__(self, "_result", (True, r))
             while self._observers:
                 try:
                     self._observers.pop().callback(r)
@@ -60,7 +60,7 @@ class ObservableDeferred(object):
             return r
 
         def errback(f):
-            self._result = (False, f)
+            object.__setattr__(self, "_result", (False, f))
             while self._observers:
                 try:
                     self._observers.pop().errback(f)
@@ -97,3 +97,8 @@ class ObservableDeferred(object):
 
     def __setattr__(self, name, value):
         setattr(self._deferred, name, value)
+
+    def __repr__(self):
+        return "<ObservableDeferred object at %s, result=%r, _deferred=%r>" % (
+            id(self), self._result, self._deferred,
+        )