From d12c00bdc311bd0685aa7e7e70f1aa7787317164 Mon Sep 17 00:00:00 2001 From: Mark Haines Date: Wed, 23 Dec 2015 15:18:11 +0000 Subject: [PATCH] Add some docstring explaining the snapshot cache does --- synapse/util/caches/snapshot_cache.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/synapse/util/caches/snapshot_cache.py b/synapse/util/caches/snapshot_cache.py index 8a7ca47a8..09f00afbc 100644 --- a/synapse/util/caches/snapshot_cache.py +++ b/synapse/util/caches/snapshot_cache.py @@ -17,8 +17,28 @@ from synapse.util.async import ObservableDeferred class SnapshotCache(object): + """Cache for snapshots like the response of /initialSync. + The response of initialSync only has to be a recent snapshot of the + server state. It shouldn't matter to clients if it is a few minutes out + of date. - DURATION_MS = 5 * 60 * 1000 # Cache results for 2 minutes. + This caches a deferred response. Until the deferred completes it will be + returned from the cache. This means that if the client retries the request + while the response is still being computed, that original response will be + used rather than trying to compute a new response. + + Once the deferred completes it will removed from the cache after 5 minutes. + We delay removing it from the cache because a client retrying its request + could race with us finishing computing the response. + + Rather than tracking precisely how long something has been in the cache we + keep two generations of completed responses. Every 5 minutes discard the + old generation, move the new generation to the old generation, and set the + new generation to be empty. This means that a result will be in the cache + somewhere between 5 and 10 minutes. + """ + + DURATION_MS = 5 * 60 * 1000 # Cache results for 5 minutes. def __init__(self): self.pending_result_cache = {} # Request that haven't finished yet. @@ -51,6 +71,8 @@ class SnapshotCache(object): result = self.pending_result_cache.get(key, result) if result is not None: return result.observe() + else: + return None def set(self, time_now_ms, key, deferred): self.rotate(time_now_ms)