summary refs log tree commit diff
path: root/synapse
diff options
context:
space:
mode:
authorErik Johnston <erik@matrix.org>2019-06-21 11:10:27 +0100
committerErik Johnston <erik@matrix.org>2019-06-21 11:10:27 +0100
commit8181e290a90bc7b7f950fb639b38d0212dca87da (patch)
treed97958fda2bcccd9878fcd1272a3b70881d779a9 /synapse
parentMerge pull request #5476 from matrix-org/erikj/histogram_extremities (diff)
downloadsynapse-8181e290a90bc7b7f950fb639b38d0212dca87da.tar.xz
Fix sync tightloop bug.
If, for some reason, presence updates take a while to persist then it
can trigger clients to tightloop calling `/sync` due to the presence
handler returning updates but not advancing the stream token.

Fixes #5503.
Diffstat (limited to 'synapse')
-rw-r--r--synapse/handlers/presence.py14
1 files changed, 12 insertions, 2 deletions
diff --git a/synapse/handlers/presence.py b/synapse/handlers/presence.py
index 5204073a38..3edd359985 100644
--- a/synapse/handlers/presence.py
+++ b/synapse/handlers/presence.py
@@ -1017,11 +1017,21 @@ class PresenceEventSource(object):
             if from_key is not None:
                 from_key = int(from_key)
 
+            max_token = self.store.get_current_presence_token()
+            if from_key == max_token:
+                # This is necessary as due to the way stream ID generators work
+                # we may get updates that have a stream ID greater than the max
+                # token. This is usually fine, as it just means that we may send
+                # down some presence updates multiple times. However, we need to
+                # be careful that the sync stream actually does make some
+                # progress, otherwise clients will end up tight looping calling
+                # /sync due to it returning the same token repeatedly. Hence
+                # this guard. C.f. #5503.
+                defer.returnValue(([], max_token))
+
             presence = self.get_presence_handler()
             stream_change_cache = self.store.presence_stream_cache
 
-            max_token = self.store.get_current_presence_token()
-
             users_interested_in = yield self._get_interested_in(user, explicit_room_id)
 
             user_ids_changed = set()