From fa16df37fcff729ef5316920dd41e8bbfcc2e1cf Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Fri, 15 Jul 2022 14:42:10 +0100 Subject: Refactor state event sending Instead of sending state events as we go, we instead calculate all state events to send and store them in a dict (ordered since Python 3.7) and then send them all at once in the end. This has no performance benefit whatsoever, but I find this clearer to reason about. My personal use case is eventually placing another layer of "custom room preset" state on top, which would be easier to do with a state map, instead of the previous code which sent state into the room as it went along. If we do eventually send all new room state simultaneously to speed up local room creation, I believe this would be an easier starting point. --- synapse/handlers/room.py | 80 +++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 41 deletions(-) diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py index 420efacb0f..38bb021c38 100644 --- a/synapse/handlers/room.py +++ b/synapse/handlers/room.py @@ -1022,7 +1022,7 @@ class RoomCreationHandler: room_id: str, room_preset_identifier: str, invite_list: List[str], - initial_state: MutableStateMap, + initial_state: MutableStateMap[JsonDict], creation_content: JsonDict, room_alias: Optional[RoomAlias] = None, power_level_content_override: Optional[JsonDict] = None, @@ -1106,13 +1106,17 @@ class RoomCreationHandler: errcode=Codes.BAD_JSON, ) + # Create and send the 'm.room.create' event creation_content.update({"creator": creator_id}) await send(etype=EventTypes.Create, content=creation_content) + assert last_sent_event_id is not None + # Create and send the join event for the room creator logger.debug("Sending %s in new room", EventTypes.Member) - # Room create event must exist at this point - assert last_sent_event_id is not None - member_event_id, _ = await self.room_member_handler.update_membership( + ( + last_sent_event_id, + last_sent_stream_id, + ) = await self.room_member_handler.update_membership( creator, creator.user, room_id, @@ -1123,15 +1127,16 @@ class RoomCreationHandler: prev_event_ids=[last_sent_event_id], depth=depth, ) - last_sent_event_id = member_event_id + + # Create a map of (event_type, state_key) -> event json dict. + # A dict allows us to easily load up and override state event definitions + state_to_send: MutableStateMap[JsonDict] = {} # We treat the power levels override specially as this needs to be one # of the first events that get sent into a room. pl_content = initial_state.pop((EventTypes.PowerLevels, ""), None) if pl_content is not None: - last_sent_stream_id = await send( - etype=EventTypes.PowerLevels, content=pl_content - ) + state_to_send[(EventTypes.PowerLevels, "")] = pl_content else: power_level_content: JsonDict = { "users": {creator_id: 100}, @@ -1179,47 +1184,40 @@ class RoomCreationHandler: if power_level_content_override: power_level_content.update(power_level_content_override) - last_sent_stream_id = await send( - etype=EventTypes.PowerLevels, content=power_level_content - ) + state_to_send[(EventTypes.PowerLevels, "")] = power_level_content - if room_alias and (EventTypes.CanonicalAlias, "") not in initial_state: - last_sent_stream_id = await send( - etype=EventTypes.CanonicalAlias, - content={"alias": room_alias.to_string()}, - ) - - if (EventTypes.JoinRules, "") not in initial_state: - last_sent_stream_id = await send( - etype=EventTypes.JoinRules, - content={"join_rule": room_preset_config["join_rules"]}, - ) + if room_alias: + state_to_send[(EventTypes.CanonicalAlias, "")] = { + "alias": room_alias.to_string() + } - if (EventTypes.RoomHistoryVisibility, "") not in initial_state: - last_sent_stream_id = await send( - etype=EventTypes.RoomHistoryVisibility, - content={ - "history_visibility": room_preset_config["history_visibility"] - }, - ) + state_to_send[(EventTypes.JoinRules, "")] = { + "join_rule": room_preset_config["join_rules"] + } + state_to_send[(EventTypes.RoomHistoryVisibility, "")] = { + "history_visibility": room_preset_config["history_visibility"] + } if room_preset_config["guest_can_join"]: - if (EventTypes.GuestAccess, "") not in initial_state: - last_sent_stream_id = await send( - etype=EventTypes.GuestAccess, - content={EventContentFields.GUEST_ACCESS: GuestAccess.CAN_JOIN}, - ) + state_to_send[(EventTypes.GuestAccess, "")] = { + EventContentFields.GUEST_ACCESS: GuestAccess.CAN_JOIN + } - for (etype, state_key), content in initial_state.items(): - last_sent_stream_id = await send( - etype=etype, state_key=state_key, content=content - ) + # Override any default state with the user-provided contents of `initial_state` + state_to_send.update(initial_state) + # Set the encryption state of the room based on the room preset config + # FIXME: We should do this before layering initial_state on top, c.f. + # https://github.com/matrix-org/synapse/issues/9794. if room_preset_config["encrypted"]: + state_to_send[(EventTypes.RoomEncryption, "")] = { + "algorithm": RoomEncryptionAlgorithms.DEFAULT + } + + # Send each event in order of its insertion into the dictionary + for (event_type, state_key), content in state_to_send.items(): last_sent_stream_id = await send( - etype=EventTypes.RoomEncryption, - state_key="", - content={"algorithm": RoomEncryptionAlgorithms.DEFAULT}, + etype=event_type, state_key=state_key, content=content ) return last_sent_stream_id, last_sent_event_id, depth -- cgit 1.4.1