summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthew Hodgson <matthew@matrix.org>2018-09-07 23:49:05 +0100
committerMatthew Hodgson <matthew@matrix.org>2018-09-07 23:49:05 +0100
commitc39754aac2c3f1320eb4d5396f8c05392e5045aa (patch)
tree72518a939ae855c09fa346692bc95a81f92fced7
parentflake8 and make API more compact & docced (diff)
downloadsynapse-c39754aac2c3f1320eb4d5396f8c05392e5045aa.tar.xz
switch to named tuple
-rw-r--r--synapse/handlers/sync.py14
-rw-r--r--synapse/storage/roommember.py49
2 files changed, 42 insertions, 21 deletions
diff --git a/synapse/handlers/sync.py b/synapse/handlers/sync.py
index 3bd851f1ca..7768c54adb 100644
--- a/synapse/handlers/sync.py
+++ b/synapse/handlers/sync.py
@@ -32,6 +32,7 @@ from synapse.util.caches.response_cache import ResponseCache
 from synapse.util.logcontext import LoggingContext
 from synapse.util.metrics import Measure, measure_func
 from synapse.visibility import filter_events_for_client
+from synapse.storage.roommember import MemberSummary
 
 logger = logging.getLogger(__name__)
 
@@ -551,27 +552,28 @@ class SyncHandler(object):
         canonical_alias_id = state_ids.get((EventTypes.CanonicalAlias, ''))
 
         summary = {}
+        empty_ms = MemberSummary([], 0)
 
         # TODO: only send these when they change.
         summary["m.joined_member_count"] = (
-            details.get(Membership.JOIN, ([], 0))[1]
+            details.get(Membership.JOIN, empty_ms).count
         )
         summary["m.invited_member_count"] = (
-            details.get(Membership.INVITE, ([], 0))[1]
+            details.get(Membership.INVITE, empty_ms).count
         )
 
         if name_id or canonical_alias_id:
             defer.returnValue(summary)
 
         joined_user_ids = [
-            r[0] for r in details.get(Membership.JOIN, ([], 0))[0]
+            r[0] for r in details.get(Membership.JOIN, empty_ms).members
         ]
         invited_user_ids = [
-            r[0] for r in details.get(Membership.INVITE, ([], 0))[0]
+            r[0] for r in details.get(Membership.INVITE, empty_ms).members
         ]
         gone_user_ids = (
-            [r[0] for r in details.get(Membership.LEAVE, ([], 0))[0]] +
-            [r[0] for r in details.get(Membership.BAN, ([], 0))[0]]
+            [r[0] for r in details.get(Membership.LEAVE, empty_ms).members] +
+            [r[0] for r in details.get(Membership.BAN, empty_ms).members]
         )
 
         # FIXME: only build up a member_ids list for our heroes
diff --git a/synapse/storage/roommember.py b/synapse/storage/roommember.py
index 526c94f808..c6a22ff3d5 100644
--- a/synapse/storage/roommember.py
+++ b/synapse/storage/roommember.py
@@ -51,6 +51,12 @@ ProfileInfo = namedtuple(
     "ProfileInfo", ("avatar_url", "display_name")
 )
 
+# "members" points to a truncated list of (user_id, event_id) tuples for users of
+# a given membership type, suitable for use in calculating heroes for a room.
+# "count" points to the total numberr of users of a given membership type.
+MemberSummary = namedtuple(
+    "MemberSummary", ("members", "count")
+)
 
 _MEMBERSHIP_PROFILE_UPDATE_NAME = "room_membership_profile_update"
 
@@ -84,36 +90,49 @@ class RoomMemberWorkerStore(EventsWorkerStore):
 
     @cached(max_entries=100000, iterable=True)
     def get_room_summary(self, room_id):
+        """ Get the details of a room roughly suitable for use by the room
+        summary extension to /sync. Useful when lazy loading room members.
+        Args:
+            room_id (str): The room ID to query
+        Returns:
+            Deferred[dict[str, MemberSummary]:
+                dict of membership states, pointing to a MemberSummary named tuple.
+        """
+
         def f(txn):
+            # first get counts.
+            # We do this all in one transaction to keep the cache small.
+            # FIXME: get rid of this when we have room_stats
             sql = (
-                "SELECT m.user_id, m.membership, m.event_id FROM room_memberships as m"
+                "SELECT count(*), m.membership FROM room_memberships as m"
                 " INNER JOIN current_state_events as c"
-                " ON m.event_id = c.event_id "
-                " AND m.room_id = c.room_id "
+                " ON m.event_id = c.event_id"
+                " AND m.room_id = c.room_id"
                 " AND m.user_id = c.state_key"
-                " WHERE c.type = 'm.room.member' AND c.room_id = ? limit ?"
+                " WHERE c.type = 'm.room.member' AND c.room_id = ?"
+                " GROUP BY m.membership"
             )
 
-            txn.execute(sql, (room_id, 5))
+            txn.execute(sql, (room_id,))
             res = {}
             for r in txn:
-                summary = res.setdefault(to_ascii(r[1]), {})
-                users = summary.setdefault('users', [])
-                users.append((to_ascii(r[0]), to_ascii(r[2])))
+                summary = res.setdefault(to_ascii(r[1]), MemberSummary([], r[0]))
 
             sql = (
-                "SELECT count(*), m.membership FROM room_memberships as m"
+                "SELECT m.user_id, m.membership, m.event_id "
+                "FROM room_memberships as m"
                 " INNER JOIN current_state_events as c"
-                " ON m.event_id = c.event_id "
-                " AND m.room_id = c.room_id "
+                " ON m.event_id = c.event_id"
+                " AND m.room_id = c.room_id"
                 " AND m.user_id = c.state_key"
-                " WHERE c.type = 'm.room.member' AND c.room_id = ? group by m.membership"
+                " WHERE c.type = 'm.room.member' AND c.room_id = ? limit ?"
             )
 
-            txn.execute(sql, (room_id,))
+            txn.execute(sql, (room_id, 5))
             for r in txn:
-                summary = res.setdefault(to_ascii(r[1]), {})
-                summary['count'] = r[0]
+                summary = res.get(to_ascii(r[1]))
+                members = summary.members
+                members.append((to_ascii(r[0]), to_ascii(r[2])))
 
             return res