Send device list updates out to servers in partially joined rooms (#13874)

Use the provided list of servers in the room from the `/send_join`
response, since we will not know which users are in the room.  This
isn't sufficient to ensure that all remote servers receive the right
device list updates, since the `/send_join` response may be inaccurate
or we may calculate the membership state of new users in the room
incorrectly.

Signed-off-by: Sean Quah <seanq@matrix.org>
This commit is contained in:
Sean Quah 2022-09-23 13:44:03 +01:00 committed by GitHub
parent c06b2b7142
commit 03c2bfb7f8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 66 additions and 2 deletions

View file

@ -23,6 +23,7 @@ from typing import (
List,
Mapping,
Optional,
Sequence,
Tuple,
)
@ -524,12 +525,53 @@ class StateStorageController:
return state_map.get(key)
async def get_current_hosts_in_room(self, room_id: str) -> List[str]:
"""Get current hosts in room based on current state."""
"""Get current hosts in room based on current state.
Blocks until we have full state for the given room. This only happens for rooms
with partial state.
Returns:
A list of hosts in the room, sorted by longest in the room first. (aka.
sorted by join with the lowest depth first).
"""
await self._partial_state_room_tracker.await_full_state(room_id)
return await self.stores.main.get_current_hosts_in_room(room_id)
async def get_current_hosts_in_room_or_partial_state_approximation(
self, room_id: str
) -> Sequence[str]:
"""Get approximation of current hosts in room based on current state.
For rooms with full state, this is equivalent to `get_current_hosts_in_room`,
with the same order of results.
For rooms with partial state, no blocking occurs. Instead, the list of hosts
in the room at the time of joining is combined with the list of hosts which
joined the room afterwards. The returned list may include hosts that are not
actually in the room and exclude hosts that are in the room, since we may
calculate state incorrectly during the partial state phase. The order of results
is arbitrary for rooms with partial state.
"""
# We have to read this list first to mitigate races with un-partial stating.
# This will be empty for rooms with full state.
hosts_at_join = await self.stores.main.get_partial_state_servers_at_join(
room_id
)
hosts_from_state = await self.stores.main.get_current_hosts_in_room(room_id)
hosts_from_state_set = set(hosts_from_state)
# First take the list of hosts based on the current state.
# For rooms with partial state, this will be missing most hosts.
hosts = list(hosts_from_state)
# Then add in the list of hosts in the room at the time we joined.
# This will be an empty list for rooms with full state.
hosts.extend(host for host in hosts_at_join if host not in hosts_from_state_set)
return hosts
async def get_users_in_room_with_profiles(
self, room_id: str
) -> Dict[str, ProfileInfo]: