Rearrange the user_directory's `_handle_deltas` function (#11035)
* Pull out `_handle_room_membership_event` * Discard excluded users early * Rearrange logic so the change is membership is effectively switched over. See PR for rationale.
This commit is contained in:
parent
b59f3281d5
commit
317e9e415c
|
@ -0,0 +1 @@
|
||||||
|
Rearrange the internal workings of the incremental user directory updates.
|
|
@ -196,63 +196,12 @@ class UserDirectoryHandler(StateDeltasHandler):
|
||||||
room_id, prev_event_id, event_id, typ
|
room_id, prev_event_id, event_id, typ
|
||||||
)
|
)
|
||||||
elif typ == EventTypes.Member:
|
elif typ == EventTypes.Member:
|
||||||
change = await self._get_key_change(
|
await self._handle_room_membership_event(
|
||||||
|
room_id,
|
||||||
prev_event_id,
|
prev_event_id,
|
||||||
event_id,
|
event_id,
|
||||||
key_name="membership",
|
state_key,
|
||||||
public_value=Membership.JOIN,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
is_remote = not self.is_mine_id(state_key)
|
|
||||||
if change is MatchChange.now_false:
|
|
||||||
# Need to check if the server left the room entirely, if so
|
|
||||||
# we might need to remove all the users in that room
|
|
||||||
is_in_room = await self.store.is_host_joined(
|
|
||||||
room_id, self.server_name
|
|
||||||
)
|
|
||||||
if not is_in_room:
|
|
||||||
logger.debug("Server left room: %r", room_id)
|
|
||||||
# Fetch all the users that we marked as being in user
|
|
||||||
# directory due to being in the room and then check if
|
|
||||||
# need to remove those users or not
|
|
||||||
user_ids = await self.store.get_users_in_dir_due_to_room(
|
|
||||||
room_id
|
|
||||||
)
|
|
||||||
|
|
||||||
for user_id in user_ids:
|
|
||||||
await self._handle_remove_user(room_id, user_id)
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
logger.debug("Server is still in room: %r", room_id)
|
|
||||||
|
|
||||||
include_in_dir = (
|
|
||||||
is_remote
|
|
||||||
or await self.store.should_include_local_user_in_dir(state_key)
|
|
||||||
)
|
|
||||||
if include_in_dir:
|
|
||||||
if change is MatchChange.no_change:
|
|
||||||
# Handle any profile changes for remote users.
|
|
||||||
# (For local users we are not forced to scan membership
|
|
||||||
# events; instead the rest of the application calls
|
|
||||||
# `handle_local_profile_change`.)
|
|
||||||
if is_remote:
|
|
||||||
await self._handle_profile_change(
|
|
||||||
state_key, room_id, prev_event_id, event_id
|
|
||||||
)
|
|
||||||
continue
|
|
||||||
|
|
||||||
if change is MatchChange.now_true: # The user joined
|
|
||||||
# This may be the first time we've seen a remote user. If
|
|
||||||
# so, ensure we have a directory entry for them. (We don't
|
|
||||||
# need to do this for local users: their directory entry
|
|
||||||
# is created at the point of registration.
|
|
||||||
if is_remote:
|
|
||||||
await self._upsert_directory_entry_for_remote_user(
|
|
||||||
state_key, event_id
|
|
||||||
)
|
|
||||||
await self._track_user_joined_room(room_id, state_key)
|
|
||||||
else: # The user left
|
|
||||||
await self._handle_remove_user(room_id, state_key)
|
|
||||||
else:
|
else:
|
||||||
logger.debug("Ignoring irrelevant type: %r", typ)
|
logger.debug("Ignoring irrelevant type: %r", typ)
|
||||||
|
|
||||||
|
@ -326,6 +275,72 @@ class UserDirectoryHandler(StateDeltasHandler):
|
||||||
for user_id in users_in_room:
|
for user_id in users_in_room:
|
||||||
await self._track_user_joined_room(room_id, user_id)
|
await self._track_user_joined_room(room_id, user_id)
|
||||||
|
|
||||||
|
async def _handle_room_membership_event(
|
||||||
|
self,
|
||||||
|
room_id: str,
|
||||||
|
prev_event_id: str,
|
||||||
|
event_id: str,
|
||||||
|
state_key: str,
|
||||||
|
) -> None:
|
||||||
|
"""Process a single room membershp event.
|
||||||
|
|
||||||
|
We have to do two things:
|
||||||
|
|
||||||
|
1. Update the room-sharing tables.
|
||||||
|
This applies to remote users and non-excluded local users.
|
||||||
|
2. Update the user_directory and user_directory_search tables.
|
||||||
|
This applies to remote users only, because we only become aware of
|
||||||
|
the (and any profile changes) by listening to these events.
|
||||||
|
The rest of the application knows exactly when local users are
|
||||||
|
created or their profile changed---it will directly call methods
|
||||||
|
on this class.
|
||||||
|
"""
|
||||||
|
joined = await self._get_key_change(
|
||||||
|
prev_event_id,
|
||||||
|
event_id,
|
||||||
|
key_name="membership",
|
||||||
|
public_value=Membership.JOIN,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Both cases ignore excluded local users, so start by discarding them.
|
||||||
|
is_remote = not self.is_mine_id(state_key)
|
||||||
|
if not is_remote and not await self.store.should_include_local_user_in_dir(
|
||||||
|
state_key
|
||||||
|
):
|
||||||
|
return
|
||||||
|
|
||||||
|
if joined is MatchChange.now_false:
|
||||||
|
# Need to check if the server left the room entirely, if so
|
||||||
|
# we might need to remove all the users in that room
|
||||||
|
is_in_room = await self.store.is_host_joined(room_id, self.server_name)
|
||||||
|
if not is_in_room:
|
||||||
|
logger.debug("Server left room: %r", room_id)
|
||||||
|
# Fetch all the users that we marked as being in user
|
||||||
|
# directory due to being in the room and then check if
|
||||||
|
# need to remove those users or not
|
||||||
|
user_ids = await self.store.get_users_in_dir_due_to_room(room_id)
|
||||||
|
|
||||||
|
for user_id in user_ids:
|
||||||
|
await self._handle_remove_user(room_id, user_id)
|
||||||
|
else:
|
||||||
|
logger.debug("Server is still in room: %r", room_id)
|
||||||
|
await self._handle_remove_user(room_id, state_key)
|
||||||
|
elif joined is MatchChange.no_change:
|
||||||
|
# Handle any profile changes for remote users.
|
||||||
|
# (For local users the rest of the application calls
|
||||||
|
# `handle_local_profile_change`.)
|
||||||
|
if is_remote:
|
||||||
|
await self._handle_possible_remote_profile_change(
|
||||||
|
state_key, room_id, prev_event_id, event_id
|
||||||
|
)
|
||||||
|
elif joined is MatchChange.now_true: # The user joined
|
||||||
|
# This may be the first time we've seen a remote user. If
|
||||||
|
# so, ensure we have a directory entry for them. (For local users,
|
||||||
|
# the rest of the application calls `handle_local_profile_change`.)
|
||||||
|
if is_remote:
|
||||||
|
await self._upsert_directory_entry_for_remote_user(state_key, event_id)
|
||||||
|
await self._track_user_joined_room(room_id, state_key)
|
||||||
|
|
||||||
async def _upsert_directory_entry_for_remote_user(
|
async def _upsert_directory_entry_for_remote_user(
|
||||||
self, user_id: str, event_id: str
|
self, user_id: str, event_id: str
|
||||||
) -> None:
|
) -> None:
|
||||||
|
@ -386,7 +401,12 @@ class UserDirectoryHandler(StateDeltasHandler):
|
||||||
await self.store.add_users_who_share_private_room(room_id, to_insert)
|
await self.store.add_users_who_share_private_room(room_id, to_insert)
|
||||||
|
|
||||||
async def _handle_remove_user(self, room_id: str, user_id: str) -> None:
|
async def _handle_remove_user(self, room_id: str, user_id: str) -> None:
|
||||||
"""Called when we might need to remove user from directory
|
"""Called when when someone leaves a room. The user may be local or remote.
|
||||||
|
|
||||||
|
(If the person who left was the last local user in this room, the server
|
||||||
|
is no longer in the room. We call this function to forget that the remaining
|
||||||
|
remote users are in the room, even though they haven't left. So the name is
|
||||||
|
a little misleading!)
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
room_id: The room ID that user left or stopped being public that
|
room_id: The room ID that user left or stopped being public that
|
||||||
|
@ -403,7 +423,7 @@ class UserDirectoryHandler(StateDeltasHandler):
|
||||||
if len(rooms_user_is_in) == 0:
|
if len(rooms_user_is_in) == 0:
|
||||||
await self.store.remove_from_user_dir(user_id)
|
await self.store.remove_from_user_dir(user_id)
|
||||||
|
|
||||||
async def _handle_profile_change(
|
async def _handle_possible_remote_profile_change(
|
||||||
self,
|
self,
|
||||||
user_id: str,
|
user_id: str,
|
||||||
room_id: str,
|
room_id: str,
|
||||||
|
@ -411,7 +431,8 @@ class UserDirectoryHandler(StateDeltasHandler):
|
||||||
event_id: Optional[str],
|
event_id: Optional[str],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Check member event changes for any profile changes and update the
|
"""Check member event changes for any profile changes and update the
|
||||||
database if there are.
|
database if there are. This is intended for remote users only. The caller
|
||||||
|
is responsible for checking that the given user is remote.
|
||||||
"""
|
"""
|
||||||
if not prev_event_id or not event_id:
|
if not prev_event_id or not event_id:
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in New Issue