Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit 317e9e4

Browse files
author
David Robertson
authored
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.
1 parent b59f328 commit 317e9e4

File tree

2 files changed

+79
-57
lines changed

2 files changed

+79
-57
lines changed

changelog.d/11035.misc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Rearrange the internal workings of the incremental user directory updates.

synapse/handlers/user_directory.py

Lines changed: 78 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -196,63 +196,12 @@ async def _handle_deltas(self, deltas: List[Dict[str, Any]]) -> None:
196196
room_id, prev_event_id, event_id, typ
197197
)
198198
elif typ == EventTypes.Member:
199-
change = await self._get_key_change(
199+
await self._handle_room_membership_event(
200+
room_id,
200201
prev_event_id,
201202
event_id,
202-
key_name="membership",
203-
public_value=Membership.JOIN,
203+
state_key,
204204
)
205-
206-
is_remote = not self.is_mine_id(state_key)
207-
if change is MatchChange.now_false:
208-
# Need to check if the server left the room entirely, if so
209-
# we might need to remove all the users in that room
210-
is_in_room = await self.store.is_host_joined(
211-
room_id, self.server_name
212-
)
213-
if not is_in_room:
214-
logger.debug("Server left room: %r", room_id)
215-
# Fetch all the users that we marked as being in user
216-
# directory due to being in the room and then check if
217-
# need to remove those users or not
218-
user_ids = await self.store.get_users_in_dir_due_to_room(
219-
room_id
220-
)
221-
222-
for user_id in user_ids:
223-
await self._handle_remove_user(room_id, user_id)
224-
continue
225-
else:
226-
logger.debug("Server is still in room: %r", room_id)
227-
228-
include_in_dir = (
229-
is_remote
230-
or await self.store.should_include_local_user_in_dir(state_key)
231-
)
232-
if include_in_dir:
233-
if change is MatchChange.no_change:
234-
# Handle any profile changes for remote users.
235-
# (For local users we are not forced to scan membership
236-
# events; instead the rest of the application calls
237-
# `handle_local_profile_change`.)
238-
if is_remote:
239-
await self._handle_profile_change(
240-
state_key, room_id, prev_event_id, event_id
241-
)
242-
continue
243-
244-
if change is MatchChange.now_true: # The user joined
245-
# This may be the first time we've seen a remote user. If
246-
# so, ensure we have a directory entry for them. (We don't
247-
# need to do this for local users: their directory entry
248-
# is created at the point of registration.
249-
if is_remote:
250-
await self._upsert_directory_entry_for_remote_user(
251-
state_key, event_id
252-
)
253-
await self._track_user_joined_room(room_id, state_key)
254-
else: # The user left
255-
await self._handle_remove_user(room_id, state_key)
256205
else:
257206
logger.debug("Ignoring irrelevant type: %r", typ)
258207

@@ -326,6 +275,72 @@ async def _handle_room_publicity_change(
326275
for user_id in users_in_room:
327276
await self._track_user_joined_room(room_id, user_id)
328277

278+
async def _handle_room_membership_event(
279+
self,
280+
room_id: str,
281+
prev_event_id: str,
282+
event_id: str,
283+
state_key: str,
284+
) -> None:
285+
"""Process a single room membershp event.
286+
287+
We have to do two things:
288+
289+
1. Update the room-sharing tables.
290+
This applies to remote users and non-excluded local users.
291+
2. Update the user_directory and user_directory_search tables.
292+
This applies to remote users only, because we only become aware of
293+
the (and any profile changes) by listening to these events.
294+
The rest of the application knows exactly when local users are
295+
created or their profile changed---it will directly call methods
296+
on this class.
297+
"""
298+
joined = await self._get_key_change(
299+
prev_event_id,
300+
event_id,
301+
key_name="membership",
302+
public_value=Membership.JOIN,
303+
)
304+
305+
# Both cases ignore excluded local users, so start by discarding them.
306+
is_remote = not self.is_mine_id(state_key)
307+
if not is_remote and not await self.store.should_include_local_user_in_dir(
308+
state_key
309+
):
310+
return
311+
312+
if joined is MatchChange.now_false:
313+
# Need to check if the server left the room entirely, if so
314+
# we might need to remove all the users in that room
315+
is_in_room = await self.store.is_host_joined(room_id, self.server_name)
316+
if not is_in_room:
317+
logger.debug("Server left room: %r", room_id)
318+
# Fetch all the users that we marked as being in user
319+
# directory due to being in the room and then check if
320+
# need to remove those users or not
321+
user_ids = await self.store.get_users_in_dir_due_to_room(room_id)
322+
323+
for user_id in user_ids:
324+
await self._handle_remove_user(room_id, user_id)
325+
else:
326+
logger.debug("Server is still in room: %r", room_id)
327+
await self._handle_remove_user(room_id, state_key)
328+
elif joined is MatchChange.no_change:
329+
# Handle any profile changes for remote users.
330+
# (For local users the rest of the application calls
331+
# `handle_local_profile_change`.)
332+
if is_remote:
333+
await self._handle_possible_remote_profile_change(
334+
state_key, room_id, prev_event_id, event_id
335+
)
336+
elif joined is MatchChange.now_true: # The user joined
337+
# This may be the first time we've seen a remote user. If
338+
# so, ensure we have a directory entry for them. (For local users,
339+
# the rest of the application calls `handle_local_profile_change`.)
340+
if is_remote:
341+
await self._upsert_directory_entry_for_remote_user(state_key, event_id)
342+
await self._track_user_joined_room(room_id, state_key)
343+
329344
async def _upsert_directory_entry_for_remote_user(
330345
self, user_id: str, event_id: str
331346
) -> None:
@@ -386,7 +401,12 @@ async def _track_user_joined_room(self, room_id: str, user_id: str) -> None:
386401
await self.store.add_users_who_share_private_room(room_id, to_insert)
387402

388403
async def _handle_remove_user(self, room_id: str, user_id: str) -> None:
389-
"""Called when we might need to remove user from directory
404+
"""Called when when someone leaves a room. The user may be local or remote.
405+
406+
(If the person who left was the last local user in this room, the server
407+
is no longer in the room. We call this function to forget that the remaining
408+
remote users are in the room, even though they haven't left. So the name is
409+
a little misleading!)
390410
391411
Args:
392412
room_id: The room ID that user left or stopped being public that
@@ -403,15 +423,16 @@ async def _handle_remove_user(self, room_id: str, user_id: str) -> None:
403423
if len(rooms_user_is_in) == 0:
404424
await self.store.remove_from_user_dir(user_id)
405425

406-
async def _handle_profile_change(
426+
async def _handle_possible_remote_profile_change(
407427
self,
408428
user_id: str,
409429
room_id: str,
410430
prev_event_id: Optional[str],
411431
event_id: Optional[str],
412432
) -> None:
413433
"""Check member event changes for any profile changes and update the
414-
database if there are.
434+
database if there are. This is intended for remote users only. The caller
435+
is responsible for checking that the given user is remote.
415436
"""
416437
if not prev_event_id or not event_id:
417438
return

0 commit comments

Comments
 (0)