From a08f32f8ed8c51ad04669a3969493248ec8128df Mon Sep 17 00:00:00 2001 From: "H. Shay" Date: Thu, 4 Aug 2022 12:16:26 -0700 Subject: split out creating and sending event --- synapse/handlers/room.py | 95 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 68 insertions(+), 27 deletions(-) diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py index 55395457c3..3d15d897cb 100644 --- a/synapse/handlers/room.py +++ b/synapse/handlers/room.py @@ -716,7 +716,7 @@ class RoomCreationHandler: if ( self._server_notices_mxid is not None - and requester.user.to_string() == self._server_notices_mxid + and user_id == self._server_notices_mxid ): # allow the server notices mxid to create rooms is_requester_admin = True @@ -1046,7 +1046,7 @@ class RoomCreationHandler: depth = 1 last_sent_event_id: Optional[str] = None - def create(etype: str, content: JsonDict, **kwargs: Any) -> JsonDict: + def create_event_dict(etype: str, content: JsonDict, **kwargs: Any) -> JsonDict: e = {"type": etype, "content": content} e.update(event_keys) @@ -1054,32 +1054,48 @@ class RoomCreationHandler: return e - async def send(etype: str, content: JsonDict, **kwargs: Any) -> int: + async def create_event( + etype: str, content: JsonDict, **kwargs: Any + ) -> Tuple[EventBase, synapse.events.snapshot.EventContext]: nonlocal last_sent_event_id nonlocal depth - 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( + event_dict = create_event_dict(etype, content, **kwargs) + + event, context = await self.event_creation_handler.create_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. + event_dict, prev_event_ids=[last_sent_event_id] if last_sent_event_id else [], depth=depth, ) - last_sent_event_id = sent_event.event_id + return event, context + + async def send( + event: EventBase, + context: synapse.events.snapshot.EventContext, + creator: Requester, + ) -> int: + nonlocal last_sent_event_id + nonlocal depth + assert self.hs.is_mine_id(event.sender), "User must be our own: %s" % ( + event.sender, + ) + + ev = await self.event_creation_handler.handle_new_client_event( + requester=creator, + event=event, + context=context, + ratelimit=False, + ignore_shadow_ban=True, + ) + + last_sent_event_id = ev.event_id depth += 1 - return last_stream_id + # we know it was persisted, so must have a stream ordering + assert ev.internal_metadata.stream_ordering + return ev.internal_metadata.stream_ordering try: config = self._presets_dict[preset_config] @@ -1089,9 +1105,13 @@ class RoomCreationHandler: ) creation_content.update({"creator": creator_id}) - await send(etype=EventTypes.Create, content=creation_content) + creation_event, creation_context = await create_event( + etype=EventTypes.Create, content=creation_content + ) logger.debug("Sending %s in new room", EventTypes.Member) + await send(creation_event, creation_context, creator) + # 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( @@ -1111,9 +1131,10 @@ class RoomCreationHandler: # 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( + power_event, power_context = await create_event( etype=EventTypes.PowerLevels, content=pl_content ) + last_sent_stream_id = await send(power_event, power_context, creator) else: power_level_content: JsonDict = { "users": {creator_id: 100}, @@ -1157,45 +1178,65 @@ class RoomCreationHandler: if power_level_content_override: power_level_content.update(power_level_content_override) - last_sent_stream_id = await send( + pl_event, pl_context = await create_event( etype=EventTypes.PowerLevels, content=power_level_content ) + last_sent_stream_id = await send(pl_event, pl_context, creator) if room_alias and (EventTypes.CanonicalAlias, "") not in initial_state: - last_sent_stream_id = await send( + room_alias_event, room_alias_context = await create_event( etype=EventTypes.CanonicalAlias, content={"alias": room_alias.to_string()}, ) + last_sent_stream_id = await send( + room_alias_event, room_alias_context, creator + ) if (EventTypes.JoinRules, "") not in initial_state: - last_sent_stream_id = await send( + join_rules_event, join_rules_context = await create_event( etype=EventTypes.JoinRules, content={"join_rule": config["join_rules"]} ) + last_sent_stream_id = await send( + join_rules_event, join_rules_context, creator + ) if (EventTypes.RoomHistoryVisibility, "") not in initial_state: - last_sent_stream_id = await send( + visibility_event, visibility_context = await create_event( etype=EventTypes.RoomHistoryVisibility, content={"history_visibility": config["history_visibility"]}, ) + last_sent_stream_id = await send( + visibility_event, visibility_context, creator + ) if config["guest_can_join"]: if (EventTypes.GuestAccess, "") not in initial_state: - last_sent_stream_id = await send( + guest_access_event, guest_access_context = await create_event( etype=EventTypes.GuestAccess, content={EventContentFields.GUEST_ACCESS: GuestAccess.CAN_JOIN}, ) + last_sent_stream_id = await send( + guest_access_event, guest_access_context, creator + ) + events = [] for (etype, state_key), content in initial_state.items(): - last_sent_stream_id = await send( + event, context = await create_event( etype=etype, state_key=state_key, content=content ) + events.append((event, context)) + for event, context in events: + last_sent_stream_id = await send(event, context, creator) if config["encrypted"]: - last_sent_stream_id = await send( + encryption_event, encryption_context = await create_event( etype=EventTypes.RoomEncryption, state_key="", content={"algorithm": RoomEncryptionAlgorithms.DEFAULT}, ) + last_sent_stream_id = await send( + encryption_event, encryption_context, creator + ) return last_sent_stream_id, last_sent_event_id, depth -- cgit 1.5.1 From e215109b744a227d2012b5f397da853e375c1a89 Mon Sep 17 00:00:00 2001 From: "H. Shay" Date: Thu, 11 Aug 2022 21:13:59 -0700 Subject: batch some events to send --- synapse/handlers/room.py | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py index 3d15d897cb..9d15f8929c 100644 --- a/synapse/handlers/room.py +++ b/synapse/handlers/room.py @@ -1040,9 +1040,7 @@ class RoomCreationHandler: """ creator_id = creator.user.to_string() - event_keys = {"room_id": room_id, "sender": creator_id, "state_key": ""} - depth = 1 last_sent_event_id: Optional[str] = None @@ -1068,7 +1066,7 @@ class RoomCreationHandler: prev_event_ids=[last_sent_event_id] if last_sent_event_id else [], depth=depth, ) - + depth += 1 return event, context async def send( @@ -1077,7 +1075,6 @@ class RoomCreationHandler: creator: Requester, ) -> int: nonlocal last_sent_event_id - nonlocal depth assert self.hs.is_mine_id(event.sender), "User must be our own: %s" % ( event.sender, ) @@ -1091,7 +1088,6 @@ class RoomCreationHandler: ) last_sent_event_id = ev.event_id - depth += 1 # we know it was persisted, so must have a stream ordering assert ev.internal_metadata.stream_ordering @@ -1126,6 +1122,7 @@ class RoomCreationHandler: depth=depth, ) last_sent_event_id = member_event_id + depth += 1 # We treat the power levels override specially as this needs to be one # of the first events that get sent into a room. @@ -1183,31 +1180,27 @@ class RoomCreationHandler: ) last_sent_stream_id = await send(pl_event, pl_context, creator) + events_to_send = [] if room_alias and (EventTypes.CanonicalAlias, "") not in initial_state: room_alias_event, room_alias_context = await create_event( etype=EventTypes.CanonicalAlias, content={"alias": room_alias.to_string()}, ) - last_sent_stream_id = await send( - room_alias_event, room_alias_context, creator - ) + events_to_send.append((room_alias_event, room_alias_context)) if (EventTypes.JoinRules, "") not in initial_state: join_rules_event, join_rules_context = await create_event( etype=EventTypes.JoinRules, content={"join_rule": config["join_rules"]} ) - last_sent_stream_id = await send( - join_rules_event, join_rules_context, creator - ) + + events_to_send.append((join_rules_event, join_rules_context)) if (EventTypes.RoomHistoryVisibility, "") not in initial_state: visibility_event, visibility_context = await create_event( etype=EventTypes.RoomHistoryVisibility, content={"history_visibility": config["history_visibility"]}, ) - last_sent_stream_id = await send( - visibility_event, visibility_context, creator - ) + events_to_send.append((visibility_event, visibility_context)) if config["guest_can_join"]: if (EventTypes.GuestAccess, "") not in initial_state: @@ -1215,18 +1208,13 @@ class RoomCreationHandler: etype=EventTypes.GuestAccess, content={EventContentFields.GUEST_ACCESS: GuestAccess.CAN_JOIN}, ) - last_sent_stream_id = await send( - guest_access_event, guest_access_context, creator - ) + events_to_send.append((guest_access_event, guest_access_context)) - events = [] for (etype, state_key), content in initial_state.items(): event, context = await create_event( etype=etype, state_key=state_key, content=content ) - events.append((event, context)) - for event, context in events: - last_sent_stream_id = await send(event, context, creator) + events_to_send.append((event, context)) if config["encrypted"]: encryption_event, encryption_context = await create_event( @@ -1234,10 +1222,10 @@ class RoomCreationHandler: state_key="", content={"algorithm": RoomEncryptionAlgorithms.DEFAULT}, ) - last_sent_stream_id = await send( - encryption_event, encryption_context, creator - ) + events_to_send.append((encryption_event, encryption_context)) + for event, context in events_to_send: + last_sent_stream_id = await send(event, context, creator) return last_sent_stream_id, last_sent_event_id, depth def _generate_room_id(self) -> str: -- cgit 1.5.1 From b8ed35841d52724f53798efa681874d5edbc907e Mon Sep 17 00:00:00 2001 From: "H. Shay" Date: Thu, 11 Aug 2022 21:15:16 -0700 Subject: fix tests to accomodate new structure of DAG after room creation --- tests/handlers/test_sync.py | 9 +++++---- tests/rest/client/test_rooms.py | 4 ++-- tests/test_federation.py | 11 ++++------- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/tests/handlers/test_sync.py b/tests/handlers/test_sync.py index e3f38fbcc5..70be9ff9d6 100644 --- a/tests/handlers/test_sync.py +++ b/tests/handlers/test_sync.py @@ -222,9 +222,10 @@ class SyncTestCase(tests.unittest.HomeserverTestCase): ) self.assertEqual(len(alice_sync_result.joined), 1) self.assertEqual(alice_sync_result.joined[0].room_id, room_id) - last_room_creation_event_id = ( - alice_sync_result.joined[0].timeline.events[-1].event_id - ) + last_room_creation_event_ids = [ + alice_sync_result.joined[0].timeline.events[-1].event_id, + alice_sync_result.joined[0].timeline.events[-2].event_id, + ] # Eve, a ne'er-do-well, registers. eve = self.register_user("eve", "password") @@ -250,7 +251,7 @@ class SyncTestCase(tests.unittest.HomeserverTestCase): self.hs.get_datastores().main, "get_prev_events_for_room", new_callable=MagicMock, - return_value=make_awaitable([last_room_creation_event_id]), + return_value=make_awaitable(last_room_creation_event_ids), ) with mocked_get_prev_events: self.helper.join(room_id, eve, tok=eve_token) diff --git a/tests/rest/client/test_rooms.py b/tests/rest/client/test_rooms.py index aa2f578441..7d551c3810 100644 --- a/tests/rest/client/test_rooms.py +++ b/tests/rest/client/test_rooms.py @@ -710,7 +710,7 @@ class RoomsCreateTestCase(RoomBase): self.assertEqual(HTTPStatus.OK, channel.code, channel.result) self.assertTrue("room_id" in channel.json_body) assert channel.resource_usage is not None - self.assertEqual(44, channel.resource_usage.db_txn_count) + self.assertEqual(36, channel.resource_usage.db_txn_count) def test_post_room_initial_state(self) -> None: # POST with initial_state config key, expect new room id @@ -723,7 +723,7 @@ class RoomsCreateTestCase(RoomBase): self.assertEqual(HTTPStatus.OK, channel.code, channel.result) self.assertTrue("room_id" in channel.json_body) assert channel.resource_usage is not None - self.assertEqual(50, channel.resource_usage.db_txn_count) + self.assertEqual(38, channel.resource_usage.db_txn_count) def test_post_room_visibility_key(self) -> None: # POST with visibility config key, expect new room id diff --git a/tests/test_federation.py b/tests/test_federation.py index 779fad1f63..9260de891e 100644 --- a/tests/test_federation.py +++ b/tests/test_federation.py @@ -46,10 +46,9 @@ class MessageAcceptTests(unittest.HomeserverTestCase): user_id = UserID("us", "test") our_user = create_requester(user_id) room_creator = self.homeserver.get_room_creation_handler() + config = {"preset": "public_chat"} self.room_id = self.get_success( - room_creator.create_room( - our_user, room_creator._presets_dict["public_chat"], ratelimit=False - ) + room_creator.create_room(our_user, config, ratelimit=False) )[0]["room_id"] self.store = self.homeserver.get_datastores().main @@ -99,10 +98,8 @@ class MessageAcceptTests(unittest.HomeserverTestCase): ) # Make sure we actually joined the room - self.assertEqual( - self.get_success(self.store.get_latest_event_ids_in_room(self.room_id))[0], - "$join:test.serv", - ) + res = self.get_success(self.store.get_latest_event_ids_in_room(self.room_id)) + assert "$join:test.serv" in res def test_cant_hide_direct_ancestors(self): """ -- cgit 1.5.1 From 740a48de76d28e91350bbc51c85968bfa59a2763 Mon Sep 17 00:00:00 2001 From: "H. Shay" Date: Thu, 11 Aug 2022 21:20:10 -0700 Subject: newsfragment --- changelog.d/13487.misc | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 changelog.d/13487.misc diff --git a/changelog.d/13487.misc b/changelog.d/13487.misc new file mode 100644 index 0000000000..c7f03ebdca --- /dev/null +++ b/changelog.d/13487.misc @@ -0,0 +1,2 @@ +Refactor ` _send_events_for_new_room` to separate creating and sending events. + _send_events_for_new_room \ No newline at end of file -- cgit 1.5.1 From 47bd7cff4e9e23ed0000894d5fce5c995f4ac650 Mon Sep 17 00:00:00 2001 From: "H. Shay" Date: Thu, 11 Aug 2022 21:29:35 -0700 Subject: fix newsfragment --- changelog.d/13487.misc | 1 - 1 file changed, 1 deletion(-) diff --git a/changelog.d/13487.misc b/changelog.d/13487.misc index c7f03ebdca..0dfd3ca108 100644 --- a/changelog.d/13487.misc +++ b/changelog.d/13487.misc @@ -1,2 +1 @@ Refactor ` _send_events_for_new_room` to separate creating and sending events. - _send_events_for_new_room \ No newline at end of file -- cgit 1.5.1 From af2a5f3893f51dcfba303c8d78ba59bef0ff5517 Mon Sep 17 00:00:00 2001 From: "H. Shay" Date: Wed, 24 Aug 2022 14:07:36 -0700 Subject: add function to create events without computing event context --- synapse/handlers/message.py | 93 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) diff --git a/synapse/handlers/message.py b/synapse/handlers/message.py index 6b03603598..d77f2c2fb6 100644 --- a/synapse/handlers/message.py +++ b/synapse/handlers/message.py @@ -549,6 +549,98 @@ class EventCreationHandler: expiry_ms=30 * 60 * 1000, ) + async def create_event_for_batch( + self, + requester: Requester, + event_dict: dict, + prev_event_ids: List[str], + txn_id: Optional[str] = None, + auth_event_ids: Optional[List[str]] = None, + require_consent: bool = True, + outlier: bool = False, + historical: bool = False, + depth: Optional[int] = None, + ) -> EventBase: + """ + Create an event for batch persisting. Notably skips computing event context. + """ + await self.auth_blocking.check_auth_blocking(requester=requester) + + if event_dict["type"] == EventTypes.Create and event_dict["state_key"] == "": + room_version_id = event_dict["content"]["room_version"] + maybe_room_version_obj = KNOWN_ROOM_VERSIONS.get(room_version_id) + if not maybe_room_version_obj: + # this can happen if support is withdrawn for a room version + raise UnsupportedRoomVersionError(room_version_id) + room_version_obj = maybe_room_version_obj + else: + try: + room_version_obj = await self.store.get_room_version( + event_dict["room_id"] + ) + except NotFoundError: + raise AuthError(403, "Unknown room") + + builder = self.event_builder_factory.for_room_version( + room_version_obj, event_dict + ) + + self.validator.validate_builder(builder) + + if builder.type == EventTypes.Member: + membership = builder.content.get("membership", None) + target = UserID.from_string(builder.state_key) + + if membership in self.membership_types_to_include_profile_data_in: + # If event doesn't include a display name, add one. + profile = self.profile_handler + content = builder.content + + try: + if "displayname" not in content: + displayname = await profile.get_displayname(target) + if displayname is not None: + content["displayname"] = displayname + if "avatar_url" not in content: + avatar_url = await profile.get_avatar_url(target) + if avatar_url is not None: + content["avatar_url"] = avatar_url + except Exception as e: + logger.info( + "Failed to get profile information for %r: %s", target, e + ) + + is_exempt = await self._is_exempt_from_privacy_policy(builder, requester) + if require_consent and not is_exempt: + await self.assert_accepted_privacy_policy(requester) + + if requester.access_token_id is not None: + builder.internal_metadata.token_id = requester.access_token_id + + if txn_id is not None: + builder.internal_metadata.txn_id = txn_id + + builder.internal_metadata.outlier = outlier + + builder.internal_metadata.historical = historical + + event = await builder.build( + prev_event_ids=prev_event_ids, + auth_event_ids=auth_event_ids, + depth=depth, + ) + + # Pass on the outlier property from the builder to the event + # after it is created + if builder.internal_metadata.outlier: + event.internal_metadata.outlier = True + + self.validator.validate_new(event, self.config) + await self._validate_event_relation(event) + logger.debug("Created event %s", event.event_id) + + return event + async def create_event( self, requester: Requester, @@ -727,7 +819,6 @@ class EventCreationHandler: ) self.validator.validate_new(event, self.config) - return event, context async def _is_exempt_from_privacy_policy( -- cgit 1.5.1 From 49686ede02ca85567c057d92fdf0e6b6fa5d8011 Mon Sep 17 00:00:00 2001 From: "H. Shay" Date: Wed, 24 Aug 2022 14:08:04 -0700 Subject: create events and contexts seperately --- synapse/handlers/room.py | 118 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 84 insertions(+), 34 deletions(-) diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py index 9d15f8929c..c5f7e1b286 100644 --- a/synapse/handlers/room.py +++ b/synapse/handlers/room.py @@ -108,6 +108,7 @@ class EventContext: class RoomCreationHandler: def __init__(self, hs: "HomeServer"): self.store = hs.get_datastores().main + self.state = hs.get_state_handler() self._storage_controllers = hs.get_storage_controllers() self.auth = hs.get_auth() self.auth_blocking = hs.get_auth_blocking() @@ -1043,6 +1044,9 @@ class RoomCreationHandler: event_keys = {"room_id": room_id, "sender": creator_id, "state_key": ""} depth = 1 last_sent_event_id: Optional[str] = None + prev_event: List[str] = [] + state_map = {} + auth_events = [] def create_event_dict(etype: str, content: JsonDict, **kwargs: Any) -> JsonDict: e = {"type": etype, "content": content} @@ -1053,21 +1057,28 @@ class RoomCreationHandler: return e async def create_event( - etype: str, content: JsonDict, **kwargs: Any - ) -> Tuple[EventBase, synapse.events.snapshot.EventContext]: - nonlocal last_sent_event_id + etype: str, + content: JsonDict, + auth_event_ids: Optional[List[str]] = None, + **kwargs: Any, + ) -> EventBase: nonlocal depth + nonlocal prev_event event_dict = create_event_dict(etype, content, **kwargs) - event, context = await self.event_creation_handler.create_event( + event = await self.event_creation_handler.create_event_for_batch( creator, event_dict, - prev_event_ids=[last_sent_event_id] if last_sent_event_id else [], + prev_event, depth=depth, + auth_event_ids=auth_event_ids, ) depth += 1 - return event, context + prev_event = [event.event_id] + state_map[(event.type, event.state_key)] = event.event_id + + return event async def send( event: EventBase, @@ -1075,9 +1086,6 @@ class RoomCreationHandler: creator: Requester, ) -> int: nonlocal last_sent_event_id - assert self.hs.is_mine_id(event.sender), "User must be our own: %s" % ( - event.sender, - ) ev = await self.event_creation_handler.handle_new_client_event( requester=creator, @@ -1101,12 +1109,15 @@ class RoomCreationHandler: ) creation_content.update({"creator": creator_id}) - creation_event, creation_context = await create_event( - etype=EventTypes.Create, content=creation_content + creation_event = await create_event( + EventTypes.Create, + creation_content, ) + creation_context = await self.state.compute_event_context(creation_event) logger.debug("Sending %s in new room", EventTypes.Member) await send(creation_event, creation_context, creator) + auth_events.append(creation_event.event_id) # Room create event must exist at this point assert last_sent_event_id is not None @@ -1122,16 +1133,19 @@ class RoomCreationHandler: depth=depth, ) last_sent_event_id = member_event_id + prev_event = [member_event_id] depth += 1 + auth_events.append(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. pl_content = initial_state.pop((EventTypes.PowerLevels, ""), None) if pl_content is not None: - power_event, power_context = await create_event( - etype=EventTypes.PowerLevels, content=pl_content - ) + power_event = await create_event(EventTypes.PowerLevels, pl_content) + power_context = await self.state.compute_event_context(power_event) + current_state_group = power_context._state_group last_sent_stream_id = await send(power_event, power_context, creator) + auth_events.append(power_event.event_id) else: power_level_content: JsonDict = { "users": {creator_id: 100}, @@ -1174,53 +1188,89 @@ class RoomCreationHandler: # apply those. if power_level_content_override: power_level_content.update(power_level_content_override) - - pl_event, pl_context = await create_event( - etype=EventTypes.PowerLevels, content=power_level_content + pl_event = await create_event( + EventTypes.PowerLevels, + power_level_content, ) + pl_context = await self.state.compute_event_context(pl_event) + current_state_group = pl_context._state_group last_sent_stream_id = await send(pl_event, pl_context, creator) + auth_events.append(pl_event.event_id) events_to_send = [] if room_alias and (EventTypes.CanonicalAlias, "") not in initial_state: - room_alias_event, room_alias_context = await create_event( - etype=EventTypes.CanonicalAlias, - content={"alias": room_alias.to_string()}, + room_alias_event = await create_event( + EventTypes.CanonicalAlias, + {"alias": room_alias.to_string()}, + ) + assert current_state_group is not None + room_alias_context = await self.state.compute_event_context_for_batched( + room_alias_event, state_map, current_state_group ) + current_state_group = room_alias_context._state_group events_to_send.append((room_alias_event, room_alias_context)) if (EventTypes.JoinRules, "") not in initial_state: - join_rules_event, join_rules_context = await create_event( - etype=EventTypes.JoinRules, content={"join_rule": config["join_rules"]} + join_rules_event = await create_event( + EventTypes.JoinRules, + {"join_rule": config["join_rules"]}, + auth_events, ) - + assert current_state_group is not None + join_rules_context = await self.state.compute_event_context_for_batched( + join_rules_event, state_map, current_state_group + ) + current_state_group = join_rules_context._state_group events_to_send.append((join_rules_event, join_rules_context)) if (EventTypes.RoomHistoryVisibility, "") not in initial_state: - visibility_event, visibility_context = await create_event( - etype=EventTypes.RoomHistoryVisibility, - content={"history_visibility": config["history_visibility"]}, + visibility_event = await create_event( + EventTypes.RoomHistoryVisibility, + {"history_visibility": config["history_visibility"]}, + auth_events, + ) + assert current_state_group is not None + visibility_context = await self.state.compute_event_context_for_batched( + visibility_event, state_map, current_state_group ) + current_state_group = visibility_context._state_group events_to_send.append((visibility_event, visibility_context)) if config["guest_can_join"]: if (EventTypes.GuestAccess, "") not in initial_state: - guest_access_event, guest_access_context = await create_event( - etype=EventTypes.GuestAccess, - content={EventContentFields.GUEST_ACCESS: GuestAccess.CAN_JOIN}, + guest_access_event = await create_event( + EventTypes.GuestAccess, + {EventContentFields.GUEST_ACCESS: GuestAccess.CAN_JOIN}, + auth_events, ) + assert current_state_group is not None + guest_access_context = ( + await self.state.compute_event_context_for_batched( + guest_access_event, state_map, current_state_group + ) + ) + current_state_group = guest_access_context._state_group events_to_send.append((guest_access_event, guest_access_context)) for (etype, state_key), content in initial_state.items(): - event, context = await create_event( - etype=etype, state_key=state_key, content=content + event = await create_event(etype, content, auth_events, state_key=state_key) + assert current_state_group is not None + context = await self.state.compute_event_context_for_batched( + event, state_map, current_state_group ) + current_state_group = context._state_group events_to_send.append((event, context)) if config["encrypted"]: - encryption_event, encryption_context = await create_event( - etype=EventTypes.RoomEncryption, + encryption_event = await create_event( + EventTypes.RoomEncryption, + {"algorithm": RoomEncryptionAlgorithms.DEFAULT}, + auth_events, state_key="", - content={"algorithm": RoomEncryptionAlgorithms.DEFAULT}, + ) + assert current_state_group is not None + encryption_context = await self.state.compute_event_context_for_batched( + encryption_event, state_map, current_state_group ) events_to_send.append((encryption_event, encryption_context)) -- cgit 1.5.1 From 28eca036bb1c10390f661d76c29c14b4c3b247da Mon Sep 17 00:00:00 2001 From: "H. Shay" Date: Wed, 24 Aug 2022 14:08:31 -0700 Subject: add function to calculate event context without pulling from db --- synapse/state/__init__.py | 65 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/synapse/state/__init__.py b/synapse/state/__init__.py index c355e4f98a..140af8bbca 100644 --- a/synapse/state/__init__.py +++ b/synapse/state/__init__.py @@ -283,7 +283,6 @@ class StateHandler: RuntimeError if `state_ids_before_event` is not provided and one or more prev events are missing or outliers. """ - assert not event.internal_metadata.is_outlier() # @@ -334,6 +333,7 @@ class StateHandler: logger.debug("calling resolve_state_groups from compute_event_context") # we've already taken into account partial state, so no need to wait for # complete state here. + entry = await self.resolve_state_groups_for_events( event.room_id, event.prev_event_ids(), @@ -421,6 +421,69 @@ class StateHandler: partial_state=partial_state, ) + async def compute_event_context_for_batched( + self, + event: EventBase, + state_ids_before_event: StateMap[str], + current_state_group: int, + ) -> EventContext: + """ + Generate an event context for an event that has not yet been persisted to the + database. Intended for use with events that are created to be persisted in a batch. + Args: + event: the event the context is being computed for + state_ids_before_event: a state map consisting of the state ids of the events + created prior to this event. + current_state_group: the current state group before the event. + """ + state_group_before_event_prev_group = None + deltas_to_state_group_before_event = None + + state_group_before_event = current_state_group + + # if the event is not state, we are set + if not event.is_state(): + return EventContext.with_state( + storage=self._storage_controllers, + state_group_before_event=state_group_before_event, + state_group=state_group_before_event, + state_delta_due_to_event={}, + prev_group=state_group_before_event_prev_group, + delta_ids=deltas_to_state_group_before_event, + partial_state=False, + ) + + # otherwise, we'll need to create a new state group for after the event + key = (event.type, event.state_key) + + if state_ids_before_event is not None: + replaces = state_ids_before_event.get(key) + + if replaces and replaces != event.event_id: + event.unsigned["replaces_state"] = replaces + + delta_ids = {key: event.event_id} + + state_group_after_event = ( + await self._state_storage_controller.store_state_group( + event.event_id, + event.room_id, + prev_group=state_group_before_event, + delta_ids=delta_ids, + current_state_ids=None, + ) + ) + + return EventContext.with_state( + storage=self._storage_controllers, + state_group=state_group_after_event, + state_group_before_event=state_group_before_event, + state_delta_due_to_event=delta_ids, + prev_group=state_group_before_event, + delta_ids=delta_ids, + partial_state=False, + ) + @measure_func() async def resolve_state_groups_for_events( self, room_id: str, event_ids: Collection[str], await_full_state: bool = True -- cgit 1.5.1 From b38f3e92179a5c8fbc8661b363e000724e99d18a Mon Sep 17 00:00:00 2001 From: "H. Shay" Date: Wed, 24 Aug 2022 14:08:47 -0700 Subject: fix test to align with new behaviour --- tests/rest/client/test_rooms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/rest/client/test_rooms.py b/tests/rest/client/test_rooms.py index 7d551c3810..6f864d6044 100644 --- a/tests/rest/client/test_rooms.py +++ b/tests/rest/client/test_rooms.py @@ -710,7 +710,7 @@ class RoomsCreateTestCase(RoomBase): self.assertEqual(HTTPStatus.OK, channel.code, channel.result) self.assertTrue("room_id" in channel.json_body) assert channel.resource_usage is not None - self.assertEqual(36, channel.resource_usage.db_txn_count) + self.assertEqual(35, channel.resource_usage.db_txn_count) def test_post_room_initial_state(self) -> None: # POST with initial_state config key, expect new room id -- cgit 1.5.1 From 2d06a39dd018abe75617a4e8c8076ba83f497068 Mon Sep 17 00:00:00 2001 From: "H. Shay" Date: Wed, 31 Aug 2022 15:30:05 -0700 Subject: reduce duplicated code --- synapse/handlers/message.py | 131 ++++++++++---------------------------------- synapse/handlers/room.py | 7 ++- 2 files changed, 33 insertions(+), 105 deletions(-) diff --git a/synapse/handlers/message.py b/synapse/handlers/message.py index ec7c73a758..1f3eca7dfa 100644 --- a/synapse/handlers/message.py +++ b/synapse/handlers/message.py @@ -554,98 +554,6 @@ class EventCreationHandler: expiry_ms=30 * 60 * 1000, ) - async def create_event_for_batch( - self, - requester: Requester, - event_dict: dict, - prev_event_ids: List[str], - txn_id: Optional[str] = None, - auth_event_ids: Optional[List[str]] = None, - require_consent: bool = True, - outlier: bool = False, - historical: bool = False, - depth: Optional[int] = None, - ) -> EventBase: - """ - Create an event for batch persisting. Notably skips computing event context. - """ - await self.auth_blocking.check_auth_blocking(requester=requester) - - if event_dict["type"] == EventTypes.Create and event_dict["state_key"] == "": - room_version_id = event_dict["content"]["room_version"] - maybe_room_version_obj = KNOWN_ROOM_VERSIONS.get(room_version_id) - if not maybe_room_version_obj: - # this can happen if support is withdrawn for a room version - raise UnsupportedRoomVersionError(room_version_id) - room_version_obj = maybe_room_version_obj - else: - try: - room_version_obj = await self.store.get_room_version( - event_dict["room_id"] - ) - except NotFoundError: - raise AuthError(403, "Unknown room") - - builder = self.event_builder_factory.for_room_version( - room_version_obj, event_dict - ) - - self.validator.validate_builder(builder) - - if builder.type == EventTypes.Member: - membership = builder.content.get("membership", None) - target = UserID.from_string(builder.state_key) - - if membership in self.membership_types_to_include_profile_data_in: - # If event doesn't include a display name, add one. - profile = self.profile_handler - content = builder.content - - try: - if "displayname" not in content: - displayname = await profile.get_displayname(target) - if displayname is not None: - content["displayname"] = displayname - if "avatar_url" not in content: - avatar_url = await profile.get_avatar_url(target) - if avatar_url is not None: - content["avatar_url"] = avatar_url - except Exception as e: - logger.info( - "Failed to get profile information for %r: %s", target, e - ) - - is_exempt = await self._is_exempt_from_privacy_policy(builder, requester) - if require_consent and not is_exempt: - await self.assert_accepted_privacy_policy(requester) - - if requester.access_token_id is not None: - builder.internal_metadata.token_id = requester.access_token_id - - if txn_id is not None: - builder.internal_metadata.txn_id = txn_id - - builder.internal_metadata.outlier = outlier - - builder.internal_metadata.historical = historical - - event = await builder.build( - prev_event_ids=prev_event_ids, - auth_event_ids=auth_event_ids, - depth=depth, - ) - - # Pass on the outlier property from the builder to the event - # after it is created - if builder.internal_metadata.outlier: - event.internal_metadata.outlier = True - - self.validator.validate_new(event, self.config) - await self._validate_event_relation(event) - logger.debug("Created event %s", event.event_id) - - return event - async def create_event( self, requester: Requester, @@ -659,6 +567,7 @@ class EventCreationHandler: outlier: bool = False, historical: bool = False, depth: Optional[int] = None, + for_batch: bool = False, ) -> Tuple[EventBase, EventContext]: """ Given a dict from a client, create a new event. @@ -710,6 +619,8 @@ class EventCreationHandler: depth: Override the depth used to order the event in the DAG. Should normally be set to None, which will cause the depth to be calculated based on the prev_events. + for_batch: Whether this event is being created for batch sending. Notably events + created for batch sending do not have their event context computed Raises: ResourceLimitError if server is blocked to some resource being @@ -777,15 +688,27 @@ class EventCreationHandler: builder.internal_metadata.historical = historical - event, context = await self.create_new_client_event( - builder=builder, - requester=requester, - allow_no_prev_events=allow_no_prev_events, - prev_event_ids=prev_event_ids, - auth_event_ids=auth_event_ids, - state_event_ids=state_event_ids, - depth=depth, - ) + if for_batch: + event = await builder.build( + prev_event_ids=prev_event_ids, + auth_event_ids=auth_event_ids, + depth=depth, + ) + # Pass on the outlier property from the builder to the event + # after it is created + if builder.internal_metadata.outlier: + event.internal_metadata.outlier = True + + else: + event, context = await self.create_new_client_event( + builder=builder, + requester=requester, + allow_no_prev_events=allow_no_prev_events, + prev_event_ids=prev_event_ids, + auth_event_ids=auth_event_ids, + state_event_ids=state_event_ids, + depth=depth, + ) # In an ideal world we wouldn't need the second part of this condition. However, # this behaviour isn't spec'd yet, meaning we should be able to deactivate this @@ -824,7 +747,11 @@ class EventCreationHandler: ) self.validator.validate_new(event, self.config) - return event, context + + if for_batch: + return event + else: + return event, context async def _is_exempt_from_privacy_policy( self, builder: EventBuilder, requester: Requester diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py index 0970e88ad5..b244222387 100644 --- a/synapse/handlers/room.py +++ b/synapse/handlers/room.py @@ -1067,12 +1067,13 @@ class RoomCreationHandler: event_dict = create_event_dict(etype, content, **kwargs) - event = await self.event_creation_handler.create_event_for_batch( + event = await self.event_creation_handler.create_event( creator, event_dict, - prev_event, - depth=depth, + prev_event_ids=prev_event, auth_event_ids=auth_event_ids, + depth=depth, + for_batch=True, ) depth += 1 prev_event = [event.event_id] -- cgit 1.5.1 From 059746dec47bf405ab8133aa6e719cc89e90dc09 Mon Sep 17 00:00:00 2001 From: "H. Shay" Date: Thu, 1 Sep 2022 14:46:25 -0700 Subject: split out creating events for batches and add helper methods for duplicated code --- synapse/handlers/message.py | 200 +++++++++++++++++++++++++++++--------------- 1 file changed, 132 insertions(+), 68 deletions(-) diff --git a/synapse/handlers/message.py b/synapse/handlers/message.py index 1f3eca7dfa..3af77a5ed4 100644 --- a/synapse/handlers/message.py +++ b/synapse/handlers/message.py @@ -63,6 +63,7 @@ from synapse.types import ( MutableStateMap, Requester, RoomAlias, + StateMap, StreamToken, UserID, create_requester, @@ -567,7 +568,6 @@ class EventCreationHandler: outlier: bool = False, historical: bool = False, depth: Optional[int] = None, - for_batch: bool = False, ) -> Tuple[EventBase, EventContext]: """ Given a dict from a client, create a new event. @@ -619,8 +619,6 @@ class EventCreationHandler: depth: Override the depth used to order the event in the DAG. Should normally be set to None, which will cause the depth to be calculated based on the prev_events. - for_batch: Whether this event is being created for batch sending. Notably events - created for batch sending do not have their event context computed Raises: ResourceLimitError if server is blocked to some resource being @@ -630,49 +628,10 @@ class EventCreationHandler: """ await self.auth_blocking.check_auth_blocking(requester=requester) - if event_dict["type"] == EventTypes.Create and event_dict["state_key"] == "": - room_version_id = event_dict["content"]["room_version"] - maybe_room_version_obj = KNOWN_ROOM_VERSIONS.get(room_version_id) - if not maybe_room_version_obj: - # this can happen if support is withdrawn for a room version - raise UnsupportedRoomVersionError(room_version_id) - room_version_obj = maybe_room_version_obj - else: - try: - room_version_obj = await self.store.get_room_version( - event_dict["room_id"] - ) - except NotFoundError: - raise AuthError(403, "Unknown room") - - builder = self.event_builder_factory.for_room_version( - room_version_obj, event_dict - ) - - self.validator.validate_builder(builder) + builder = await self._get_and_validate_builder(event_dict) if builder.type == EventTypes.Member: - membership = builder.content.get("membership", None) - target = UserID.from_string(builder.state_key) - - if membership in self.membership_types_to_include_profile_data_in: - # If event doesn't include a display name, add one. - profile = self.profile_handler - content = builder.content - - try: - if "displayname" not in content: - displayname = await profile.get_displayname(target) - if displayname is not None: - content["displayname"] = displayname - if "avatar_url" not in content: - avatar_url = await profile.get_avatar_url(target) - if avatar_url is not None: - content["avatar_url"] = avatar_url - except Exception as e: - logger.info( - "Failed to get profile information for %r: %s", target, e - ) + await self._build_profile_data(builder) is_exempt = await self._is_exempt_from_privacy_policy(builder, requester) if require_consent and not is_exempt: @@ -688,27 +647,15 @@ class EventCreationHandler: builder.internal_metadata.historical = historical - if for_batch: - event = await builder.build( - prev_event_ids=prev_event_ids, - auth_event_ids=auth_event_ids, - depth=depth, - ) - # Pass on the outlier property from the builder to the event - # after it is created - if builder.internal_metadata.outlier: - event.internal_metadata.outlier = True - - else: - event, context = await self.create_new_client_event( - builder=builder, - requester=requester, - allow_no_prev_events=allow_no_prev_events, - prev_event_ids=prev_event_ids, - auth_event_ids=auth_event_ids, - state_event_ids=state_event_ids, - depth=depth, - ) + event, context = await self.create_new_client_event( + builder=builder, + requester=requester, + allow_no_prev_events=allow_no_prev_events, + prev_event_ids=prev_event_ids, + auth_event_ids=auth_event_ids, + state_event_ids=state_event_ids, + depth=depth, + ) # In an ideal world we wouldn't need the second part of this condition. However, # this behaviour isn't spec'd yet, meaning we should be able to deactivate this @@ -748,10 +695,127 @@ class EventCreationHandler: self.validator.validate_new(event, self.config) - if for_batch: - return event + return event, context + + async def create_event_for_batch( + self, + requester: Requester, + event_dict: dict, + prev_event_ids: List[str], + depth: int, + state_map: StateMap, + txn_id: Optional[str] = None, + require_consent: bool = True, + outlier: bool = False, + ) -> EventBase: + """ + Given a dict from a client, create a new event. Notably does not create an event + context. Adds display names to Join membership events. + + Args: + requester + event_dict: An entire event + txn_id + prev_event_ids: + the forward extremities to use as the prev_events for the + new event. + state_map: a state_map of previously created events for batching. Will be used + to calculate the auth_ids for the event, as the previously created events for + batching will not yet have been persisted to the db + require_consent: Whether to check if the requester has + consented to the privacy policy. + outlier: Indicates whether the event is an `outlier`, i.e. if + it's from an arbitrary point and floating in the DAG as + opposed to being inline with the current DAG. + depth: Override the depth used to order the event in the DAG. + + Returns: + the created event + """ + await self.auth_blocking.check_auth_blocking(requester=requester) + + builder = await self._get_and_validate_builder(event_dict) + + if builder.type == EventTypes.Member: + await self._build_profile_data(builder) + + is_exempt = await self._is_exempt_from_privacy_policy(builder, requester) + if require_consent and not is_exempt: + await self.assert_accepted_privacy_policy(requester) + + if requester.access_token_id is not None: + builder.internal_metadata.token_id = requester.access_token_id + + if txn_id is not None: + builder.internal_metadata.txn_id = txn_id + + builder.internal_metadata.outlier = outlier + + auth_ids = self._event_auth_handler.compute_auth_events(builder, state_map) + event = await builder.build( + prev_event_ids=prev_event_ids, + auth_event_ids=auth_ids, + depth=depth, + ) + # Pass on the outlier property from the builder to the event + # after it is created + if builder.internal_metadata.outlier: + event.internal_metadata.outlier = True + + self.validator.validate_new(event, self.config) + + return event + + async def _build_profile_data(self, builder: EventBuilder) -> None: + """ + Helper method to add profile information to membership event + """ + membership = builder.content.get("membership", None) + target = UserID.from_string(builder.state_key) + + if membership in self.membership_types_to_include_profile_data_in: + # If event doesn't include a display name, add one. + profile = self.profile_handler + content = builder.content + + try: + if "displayname" not in content: + displayname = await profile.get_displayname(target) + if displayname is not None: + content["displayname"] = displayname + if "avatar_url" not in content: + avatar_url = await profile.get_avatar_url(target) + if avatar_url is not None: + content["avatar_url"] = avatar_url + except Exception as e: + logger.info("Failed to get profile information for %r: %s", target, e) + + async def _get_and_validate_builder(self, event_dict: dict) -> EventBuilder: + """ + Helper method to create and validate a builder object when creating an event + """ + if event_dict["type"] == EventTypes.Create and event_dict["state_key"] == "": + room_version_id = event_dict["content"]["room_version"] + maybe_room_version_obj = KNOWN_ROOM_VERSIONS.get(room_version_id) + if not maybe_room_version_obj: + # this can happen if support is withdrawn for a room version + raise UnsupportedRoomVersionError(room_version_id) + room_version_obj = maybe_room_version_obj else: - return event, context + try: + room_version_obj = await self.store.get_room_version( + event_dict["room_id"] + ) + except NotFoundError: + raise AuthError(403, "Unknown room") + + builder = self.event_builder_factory.for_room_version( + room_version_obj, event_dict + ) + + self.validator.validate_builder(builder) + + return builder async def _is_exempt_from_privacy_policy( self, builder: EventBuilder, requester: Requester -- cgit 1.5.1 From 070f1bb720ba72bd1ae85b604e7841388be9864e Mon Sep 17 00:00:00 2001 From: "H. Shay" Date: Thu, 1 Sep 2022 14:46:57 -0700 Subject: ditch auth events and pass state map instead --- synapse/handlers/room.py | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py index b244222387..bf1af40b6c 100644 --- a/synapse/handlers/room.py +++ b/synapse/handlers/room.py @@ -120,6 +120,7 @@ class RoomCreationHandler: self._event_auth_handler = hs.get_event_auth_handler() self.config = hs.config self.request_ratelimiter = hs.get_request_ratelimiter() + self.builder = hs.get_event_builder_factory() # Room state based off defined presets self._presets_dict: Dict[str, Dict[str, Any]] = { @@ -1043,10 +1044,14 @@ class RoomCreationHandler: creator_id = creator.user.to_string() event_keys = {"room_id": room_id, "sender": creator_id, "state_key": ""} depth = 1 + # the last event sent/persisted to the db last_sent_event_id: Optional[str] = None + # the most recently created event prev_event: List[str] = [] - state_map = {} - auth_events = [] + # a map of event types, state keys -> event_ids. We collect these mappings this as events are + # created (but not persisted to the db) to determine state for future created events + # (as this info can't be pulled from the db) + state_map: dict = {} def create_event_dict(etype: str, content: JsonDict, **kwargs: Any) -> JsonDict: e = {"type": etype, "content": content} @@ -1059,7 +1064,6 @@ class RoomCreationHandler: async def create_event( etype: str, content: JsonDict, - auth_event_ids: Optional[List[str]] = None, **kwargs: Any, ) -> EventBase: nonlocal depth @@ -1067,13 +1071,12 @@ class RoomCreationHandler: event_dict = create_event_dict(etype, content, **kwargs) - event = await self.event_creation_handler.create_event( + event = await self.event_creation_handler.create_event_for_batch( creator, event_dict, - prev_event_ids=prev_event, - auth_event_ids=auth_event_ids, - depth=depth, - for_batch=True, + prev_event, + depth, + state_map, ) depth += 1 prev_event = [event.event_id] @@ -1118,7 +1121,6 @@ class RoomCreationHandler: logger.debug("Sending %s in new room", EventTypes.Member) await send(creation_event, creation_context, creator) - auth_events.append(creation_event.event_id) # Room create event must exist at this point assert last_sent_event_id is not None @@ -1135,8 +1137,11 @@ class RoomCreationHandler: ) last_sent_event_id = member_event_id prev_event = [member_event_id] + + # update the depth and state map here as these are otherwise updated in 'create_event' + # the membership event has been created through a different code path depth += 1 - auth_events.append(member_event_id) + state_map[(EventTypes.Member, creator.user.to_string())] = 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. @@ -1146,7 +1151,6 @@ class RoomCreationHandler: power_context = await self.state.compute_event_context(power_event) current_state_group = power_context._state_group last_sent_stream_id = await send(power_event, power_context, creator) - auth_events.append(power_event.event_id) else: power_level_content: JsonDict = { "users": {creator_id: 100}, @@ -1196,7 +1200,6 @@ class RoomCreationHandler: pl_context = await self.state.compute_event_context(pl_event) current_state_group = pl_context._state_group last_sent_stream_id = await send(pl_event, pl_context, creator) - auth_events.append(pl_event.event_id) events_to_send = [] if room_alias and (EventTypes.CanonicalAlias, "") not in initial_state: @@ -1215,7 +1218,6 @@ class RoomCreationHandler: join_rules_event = await create_event( EventTypes.JoinRules, {"join_rule": config["join_rules"]}, - auth_events, ) assert current_state_group is not None join_rules_context = await self.state.compute_event_context_for_batched( @@ -1228,7 +1230,6 @@ class RoomCreationHandler: visibility_event = await create_event( EventTypes.RoomHistoryVisibility, {"history_visibility": config["history_visibility"]}, - auth_events, ) assert current_state_group is not None visibility_context = await self.state.compute_event_context_for_batched( @@ -1242,7 +1243,6 @@ class RoomCreationHandler: guest_access_event = await create_event( EventTypes.GuestAccess, {EventContentFields.GUEST_ACCESS: GuestAccess.CAN_JOIN}, - auth_events, ) assert current_state_group is not None guest_access_context = ( @@ -1254,7 +1254,7 @@ class RoomCreationHandler: events_to_send.append((guest_access_event, guest_access_context)) for (etype, state_key), content in initial_state.items(): - event = await create_event(etype, content, auth_events, state_key=state_key) + event = await create_event(etype, content, state_key=state_key) assert current_state_group is not None context = await self.state.compute_event_context_for_batched( event, state_map, current_state_group @@ -1266,7 +1266,6 @@ class RoomCreationHandler: encryption_event = await create_event( EventTypes.RoomEncryption, {"algorithm": RoomEncryptionAlgorithms.DEFAULT}, - auth_events, state_key="", ) assert current_state_group is not None -- cgit 1.5.1 From 6630daba47c68d8e5e17ebf65077136c0ddc0659 Mon Sep 17 00:00:00 2001 From: "H. Shay" Date: Thu, 1 Sep 2022 14:47:10 -0700 Subject: fix tests to reflect new reality --- tests/rest/client/test_rooms.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/rest/client/test_rooms.py b/tests/rest/client/test_rooms.py index 6f864d6044..80ed7b6fd2 100644 --- a/tests/rest/client/test_rooms.py +++ b/tests/rest/client/test_rooms.py @@ -710,7 +710,7 @@ class RoomsCreateTestCase(RoomBase): self.assertEqual(HTTPStatus.OK, channel.code, channel.result) self.assertTrue("room_id" in channel.json_body) assert channel.resource_usage is not None - self.assertEqual(35, channel.resource_usage.db_txn_count) + self.assertEqual(36, channel.resource_usage.db_txn_count) def test_post_room_initial_state(self) -> None: # POST with initial_state config key, expect new room id @@ -723,7 +723,7 @@ class RoomsCreateTestCase(RoomBase): self.assertEqual(HTTPStatus.OK, channel.code, channel.result) self.assertTrue("room_id" in channel.json_body) assert channel.resource_usage is not None - self.assertEqual(38, channel.resource_usage.db_txn_count) + self.assertEqual(39, channel.resource_usage.db_txn_count) def test_post_room_visibility_key(self) -> None: # POST with visibility config key, expect new room id -- cgit 1.5.1