diff --git a/changelog.d/13210.misc b/changelog.d/13210.misc
new file mode 100644
index 0000000000..407791b8e5
--- /dev/null
+++ b/changelog.d/13210.misc
@@ -0,0 +1 @@
+Reduce number of events queried during room creation. Contributed by Nick @ Beeper (@fizzadar).
diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py
index 8dd94cbc76..a54f163c0a 100644
--- a/synapse/handlers/room.py
+++ b/synapse/handlers/room.py
@@ -1019,6 +1019,8 @@ class RoomCreationHandler:
event_keys = {"room_id": room_id, "sender": creator_id, "state_key": ""}
+ last_sent_event_id: Optional[str] = None
+
def create(etype: str, content: JsonDict, **kwargs: Any) -> JsonDict:
e = {"type": etype, "content": content}
@@ -1028,19 +1030,27 @@ class RoomCreationHandler:
return e
async def send(etype: str, content: JsonDict, **kwargs: Any) -> int:
+ nonlocal last_sent_event_id
+
event = create(etype, content, **kwargs)
logger.debug("Sending %s in new room", etype)
# Allow these events to be sent even if the user is shadow-banned to
# allow the room creation to complete.
(
- _,
+ sent_event,
last_stream_id,
) = await self.event_creation_handler.create_and_send_nonmember_event(
creator,
event,
ratelimit=False,
ignore_shadow_ban=True,
+ # Note: we don't pass state_event_ids here because this triggers
+ # an additional query per event to look them up from the events table.
+ prev_event_ids=[last_sent_event_id] if last_sent_event_id else [],
)
+
+ last_sent_event_id = sent_event.event_id
+
return last_stream_id
try:
@@ -1054,7 +1064,9 @@ class RoomCreationHandler:
await send(etype=EventTypes.Create, content=creation_content)
logger.debug("Sending %s in new room", EventTypes.Member)
- await self.room_member_handler.update_membership(
+ # 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(
creator,
creator.user,
room_id,
@@ -1062,7 +1074,9 @@ class RoomCreationHandler:
ratelimit=ratelimit,
content=creator_join_profile,
new_room=True,
+ prev_event_ids=[last_sent_event_id],
)
+ last_sent_event_id = member_event_id
# We treat the power levels override specially as this needs to be one
# of the first events that get sent into a room.
diff --git a/tests/rest/client/test_rooms.py b/tests/rest/client/test_rooms.py
index e67844cfa1..d19b1bb858 100644
--- a/tests/rest/client/test_rooms.py
+++ b/tests/rest/client/test_rooms.py
@@ -708,6 +708,21 @@ class RoomsCreateTestCase(RoomBase):
self.assertEqual(200, channel.code, channel.result)
self.assertTrue("room_id" in channel.json_body)
+ assert channel.resource_usage is not None
+ self.assertEqual(33, channel.resource_usage.db_txn_count)
+
+ def test_post_room_initial_state(self) -> None:
+ # POST with initial_state config key, expect new room id
+ channel = self.make_request(
+ "POST",
+ "/createRoom",
+ b'{"initial_state":[{"type": "m.bridge", "content": {}}]}',
+ )
+
+ self.assertEqual(200, channel.code, channel.result)
+ self.assertTrue("room_id" in channel.json_body)
+ assert channel.resource_usage is not None
+ self.assertEqual(37, channel.resource_usage.db_txn_count)
def test_post_room_visibility_key(self) -> None:
# POST with visibility config key, expect new room id
|