-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Faster joins: Refactor handling of servers in room #14954
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Faster room joins: Refactor internal handling of servers in room to never store an empty list. | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -110,7 +110,8 @@ class SendJoinResult: | |
# True if 'state' elides non-critical membership events | ||
partial_state: bool | ||
|
||
# if 'partial_state' is set, a list of the servers in the room (otherwise empty) | ||
# If 'partial_state' is set, a list of the servers in the room (otherwise empty). | ||
# Always contains the server we joined off. | ||
servers_in_room: List[str] | ||
|
||
|
||
|
@@ -1152,23 +1153,30 @@ async def _execute(pdu: EventBase) -> None: | |
% (auth_chain_create_events,) | ||
) | ||
|
||
if response.members_omitted and not response.servers_in_room: | ||
raise InvalidResponseError( | ||
"members_omitted was set, but no servers were listed in the room" | ||
) | ||
servers_in_room = response.servers_in_room | ||
if response.members_omitted: | ||
if not servers_in_room: | ||
raise InvalidResponseError( | ||
"members_omitted was set, but no servers were listed in the room" | ||
) | ||
|
||
if response.members_omitted and not partial_state: | ||
raise InvalidResponseError( | ||
"members_omitted was set, but we asked for full state" | ||
) | ||
if destination not in servers_in_room: | ||
# `servers_in_room` is supposed to be a complete list. | ||
# Fix things up if the remote homeserver is badly behaved. | ||
servers_in_room = [destination] + servers_in_room | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we be making this a set? What if the remote server returns the same thing for Is it possible for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's a good question. We'll fail to insert the list into the database, because there's a unique constraint. And the join will fail. There's nothing stopping There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Representing the server list as a set sounds like a good idea, so I did it in 163c68c. |
||
|
||
if not partial_state: | ||
raise InvalidResponseError( | ||
"members_omitted was set, but we asked for full state" | ||
) | ||
Comment on lines
+1167
to
+1170
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd recommend moving this above the destination check to have all the error checking up-front. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done in 163c68c. |
||
|
||
return SendJoinResult( | ||
event=event, | ||
state=signed_state, | ||
auth_chain=signed_auth, | ||
origin=destination, | ||
partial_state=response.members_omitted, | ||
servers_in_room=response.servers_in_room or [], | ||
servers_in_room=servers_in_room or [], | ||
) | ||
|
||
# MSC3083 defines additional error codes for room joins. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -447,7 +447,7 @@ async def handle_event(event: EventBase) -> None: | |
) | ||
) | ||
|
||
if len(partial_state_destinations) > 0: | ||
if partial_state_destinations is not None: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I initially thought there was a bug here, where we would block on the full state of the room (below) when the server we joined off returned an empty list of servers in the room. But while writing this PR to fix the bug, I discovered that we validate that the list is truthy and so the bug can't happen. |
||
destinations = partial_state_destinations | ||
|
||
if destinations is None: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -859,6 +859,7 @@ async def handle_room_un_partial_stated(self, room_id: str) -> None: | |
known_hosts_at_join = await self.store.get_partial_state_servers_at_join( | ||
room_id | ||
) | ||
assert known_hosts_at_join is not None | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be an error? Usually assertions are used for programming errors, but this seem to be input validation? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The assert can't (shouldn't?) ever be hit unless we've introduced a bug. This method is only run when we're about to finish syncing state. At that point the room is still partial stated, which implies we have a list of servers in it. |
||
potentially_changed_hosts.difference_update(known_hosts_at_join) | ||
|
||
potentially_changed_hosts.discard(self.server_name) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this fixing a bug? A potential bug? Or just clean-up?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's somewhere in between fixing a potential bug and a clean up. Probably closer to a clean up.