summary refs log tree commit diff
diff options
context:
space:
mode:
authorAndrew Morgan <andrewm@element.io>2022-07-15 14:42:10 +0100
committerAndrew Morgan <andrewm@element.io>2022-08-15 17:43:00 +0100
commitfa16df37fcff729ef5316920dd41e8bbfcc2e1cf (patch)
tree6ef296480201b76a582815878d00884fdcf0adb2
parentGive a clearer name to the variables holding preset IDs and configs (diff)
downloadsynapse-fa16df37fcff729ef5316920dd41e8bbfcc2e1cf.tar.xz
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.
-rw-r--r--synapse/handlers/room.py80
1 files 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