summary refs log tree commit diff
path: root/synapse/handlers/presence.py
diff options
context:
space:
mode:
authorPaul "LeoNerd" Evans <paul@matrix.org>2015-04-23 18:40:19 +0100
committerPaul "LeoNerd" Evans <paul@matrix.org>2015-04-23 18:40:19 +0100
commit8a785c3006327076245428d26e5ca1634e9caeb2 (patch)
tree344e0e077dbe0e1c1d54ed6bf9d436d0f5810075 /synapse/handlers/presence.py
parentGenerate presence event-stream JSON structures directly (diff)
downloadsynapse-8a785c3006327076245428d26e5ca1634e9caeb2.tar.xz
Store a list of the presence serial number at which remote users went offline, so that when we delete them from the cachemap, we can still synthesize OFFLINE events for them (SYN-261)
Diffstat (limited to '')
-rw-r--r--synapse/handlers/presence.py21
1 files changed, 21 insertions, 0 deletions
diff --git a/synapse/handlers/presence.py b/synapse/handlers/presence.py
index 6332f50974..42fb622c48 100644
--- a/synapse/handlers/presence.py
+++ b/synapse/handlers/presence.py
@@ -135,6 +135,9 @@ class PresenceHandler(BaseHandler):
         self._remote_sendmap = {}
         # map remote users to sets of local users who're interested in them
         self._remote_recvmap = {}
+        # list of (serial, set of(userids)) tuples, ordered by serial, latest
+        # first
+        self._remote_offline_serials = []
 
         # map any user to a UserPresenceCache
         self._user_cachemap = {}
@@ -715,6 +718,10 @@ class PresenceHandler(BaseHandler):
             )
 
             if state["presence"] == PresenceState.OFFLINE:
+                self._remote_offline_serials.insert(
+                    0,
+                    (self._user_cachemap_latest_serial, set([user.to_string()]))
+                )
                 del self._user_cachemap[user]
 
         for poll in content.get("poll", []):
@@ -856,6 +863,20 @@ class PresenceEventSource(object):
 
         # TODO(paul): limit
 
+        for serial, user_ids in presence._remote_offline_serials:
+            if serial < from_key:
+                break
+
+            for u in user_ids:
+                updates.append({
+                    "type": "m.presence",
+                    "content": {"user_id": u, "presence": PresenceState.OFFLINE},
+                })
+        # TODO(paul): For the v2 API we want to tell the client their from_key
+        #   is too old if we fell off the end of the _remote_offline_serials
+        #   list, and get them to invalidate+resync. In v1 we have no such
+        #   concept so this is a best-effort result.
+
         if updates:
             defer.returnValue((updates, latest_serial))
         else: