Optimise createRoom with multiple invites (#8559)

By not dropping the membership lock between invites, we can stop joins from
grabbing the lock when we're half-done and slowing the whole thing down.
pull/8685/head
Richard van der Hoff 2020-10-29 11:48:39 +00:00 committed by GitHub
parent 00b24aa545
commit 56f0ee78a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 25 additions and 13 deletions

1
changelog.d/8559.misc Normal file
View File

@ -0,0 +1 @@
Optimise `/createRoom` with multiple invited users.

View File

@ -771,22 +771,29 @@ class RoomCreationHandler(BaseHandler):
ratelimit=False,
)
for invitee in invite_list:
# we avoid dropping the lock between invites, as otherwise joins can
# start coming in and making the createRoom slow.
#
# we also don't need to check the requester's shadow-ban here, as we
# have already done so above (and potentially emptied invite_list).
with (await self.room_member_handler.member_linearizer.queue((room_id,))):
content = {}
is_direct = config.get("is_direct", None)
if is_direct:
content["is_direct"] = is_direct
# Note that update_membership with an action of "invite" can raise a
# ShadowBanError, but this was handled above by emptying invite_list.
_, last_stream_id = await self.room_member_handler.update_membership(
requester,
UserID.from_string(invitee),
room_id,
"invite",
ratelimit=False,
content=content,
)
for invitee in invite_list:
(
_,
last_stream_id,
) = await self.room_member_handler.update_membership_locked(
requester,
UserID.from_string(invitee),
room_id,
"invite",
ratelimit=False,
content=content,
)
for invite_3pid in invite_3pid_list:
id_server = invite_3pid["id_server"]

View File

@ -307,7 +307,7 @@ class RoomMemberHandler(metaclass=abc.ABCMeta):
key = (room_id,)
with (await self.member_linearizer.queue(key)):
result = await self._update_membership(
result = await self.update_membership_locked(
requester,
target,
room_id,
@ -322,7 +322,7 @@ class RoomMemberHandler(metaclass=abc.ABCMeta):
return result
async def _update_membership(
async def update_membership_locked(
self,
requester: Requester,
target: UserID,
@ -335,6 +335,10 @@ class RoomMemberHandler(metaclass=abc.ABCMeta):
content: Optional[dict] = None,
require_consent: bool = True,
) -> Tuple[str, int]:
"""Helper for update_membership.
Assumes that the membership linearizer is already held for the room.
"""
content_specified = bool(content)
if content is None:
content = {}