summary refs log tree commit diff
diff options
context:
space:
mode:
authorEric Eastwood <erice@element.io>2022-09-29 17:24:26 -0500
committerEric Eastwood <erice@element.io>2022-09-29 17:24:26 -0500
commit99a623d2095f25909136b60043672a539266e167 (patch)
tree37969f28624801f3b5235b52f4c87f30d53badbb
parentDon't require `setuptools_rust` at runtime (#13952) (diff)
downloadsynapse-99a623d2095f25909136b60043672a539266e167.tar.xz
Check appservice user interest against the local users instead of all users
`get_local_users_in_room` is way more performant since it looks at a single
table (`local_current_membership`) and is looking through way less
data since it only worries about the local users in the room instead
of everyone in the room across the federation.

Fix https://github.com/matrix-org/synapse/issues/13942

Related to:

 - https://github.com/matrix-org/synapse/pull/13605
 - https://github.com/matrix-org/synapse/pull/13608
 - https://github.com/matrix-org/synapse/pull/13606
-rw-r--r--synapse/appservice/__init__.py10
-rw-r--r--synapse/handlers/room_member.py2
-rw-r--r--synapse/handlers/user_directory.py1
-rw-r--r--synapse/storage/databases/main/appservice.py14
-rw-r--r--synapse/storage/databases/main/roommember.py19
5 files changed, 30 insertions, 16 deletions
diff --git a/synapse/appservice/__init__.py b/synapse/appservice/__init__.py
index 0dfa00df44..71b534b039 100644
--- a/synapse/appservice/__init__.py
+++ b/synapse/appservice/__init__.py
@@ -172,15 +172,11 @@ class ApplicationService:
         Returns:
             True if this service would like to know about this room.
         """
-        member_list = await store.get_users_in_room(
-            room_id, on_invalidate=cache_context.invalidate
+        app_service_users_in_room = await store.get_app_service_users_in_room(
+            room_id, self, on_invalidate=cache_context.invalidate
         )
 
-        # check joined member events
-        for user_id in member_list:
-            if self.is_interested_in_user(user_id):
-                return True
-        return False
+        return len(app_service_users_in_room) > 0
 
     def is_interested_in_user(
         self,
diff --git a/synapse/handlers/room_member.py b/synapse/handlers/room_member.py
index 88158822e0..96cc6eae71 100644
--- a/synapse/handlers/room_member.py
+++ b/synapse/handlers/room_member.py
@@ -1150,7 +1150,7 @@ class RoomMemberHandler(metaclass=abc.ABCMeta):
         logger.info("Transferring room state from %s to %s", old_room_id, room_id)
 
         # Find all local users that were in the old room and copy over each user's state
-        users = await self.store.get_users_in_room(old_room_id)
+        users = await self.store.get_local_users_in_room(old_room_id)
         await self.copy_user_state_on_room_upgrade(old_room_id, room_id, users)
 
         # Add new room to the room directory if the old room was there
diff --git a/synapse/handlers/user_directory.py b/synapse/handlers/user_directory.py
index 8c3c52e1ca..19df4de439 100644
--- a/synapse/handlers/user_directory.py
+++ b/synapse/handlers/user_directory.py
@@ -392,6 +392,7 @@ class UserDirectoryHandler(StateDeltasHandler):
         if is_public:
             await self.store.add_users_in_public_rooms(room_id, (user_id,))
         else:
+            # TODO: get_local_users_in_room here
             users_in_room = await self.store.get_users_in_room(room_id)
             other_users_in_room = [
                 other
diff --git a/synapse/storage/databases/main/appservice.py b/synapse/storage/databases/main/appservice.py
index 64b70a7b28..26fd4fa31a 100644
--- a/synapse/storage/databases/main/appservice.py
+++ b/synapse/storage/databases/main/appservice.py
@@ -157,7 +157,19 @@ class ApplicationServiceWorkerStore(RoomMemberWorkerStore):
         app_service: "ApplicationService",
         cache_context: _CacheContext,
     ) -> List[str]:
-        users_in_room = await self.get_users_in_room(
+        """
+        Get all users in a room that the appservice controls.
+
+        Args:
+            room_id: The room to check in.
+            app_service: The application service to check interest/control against
+
+        Returns:
+            List of user IDs that the appservice controls.
+        """
+        # We can use `get_local_users_in_room(...)` here because an application
+        # service can only act on behalf of users of the server it's on.
+        users_in_room = await self.get_local_users_in_room(
             room_id, on_invalidate=cache_context.invalidate
         )
         return list(filter(app_service.is_interested_in_user, users_in_room))
diff --git a/synapse/storage/databases/main/roommember.py b/synapse/storage/databases/main/roommember.py
index 982e1f08e3..8a9e553397 100644
--- a/synapse/storage/databases/main/roommember.py
+++ b/synapse/storage/databases/main/roommember.py
@@ -152,13 +152,18 @@ class RoomMemberWorkerStore(EventsWorkerStore):
         `get_current_hosts_in_room()` and so we can re-use the cache but it's
         not horrible to have here either.
 
-        Uses `m.room.member`s in the room state at the current forward extremities to
-        determine which users are in the room.
-
-        Will return inaccurate results for rooms with partial state, since the state for
-        the forward extremities of those rooms will exclude most members. We may also
-        calculate room state incorrectly for such rooms and believe that a member is or
-        is not in the room when the opposite is true.
+        Uses `m.room.member`s in the room state at the current forward
+        extremities to determine which users are in the room.
+
+        Will return inaccurate results for rooms with partial state, since the
+        state for the forward extremities of those rooms will exclude most
+        members. We may also calculate room state incorrectly for such rooms and
+        believe that a member is or is not in the room when the opposite is
+        true.
+
+        Note: If you only care about users in the room local to the homeserver,
+        use `get_local_users_in_room(...)` instead which will be more
+        performant.
         """
         return await self.db_pool.runInteraction(
             "get_users_in_room", self.get_users_in_room_txn, room_id