summary refs log tree commit diff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--host/Rory-ovh/services/containers/shared.nix2
-rw-r--r--packages/overlays/matrix-synapse/patches/0001-Fast-auth-links.patch2
-rw-r--r--packages/overlays/matrix-synapse/patches/0002-Hotfix-ignore-rejected-events-in-delayed_events.patch2
-rw-r--r--packages/overlays/matrix-synapse/patches/0003-Add-too-much-logging-to-room-summary-over-federation.patch2
-rw-r--r--packages/overlays/matrix-synapse/patches/0004-Log-entire-room-if-accessibility-check-fails.patch2
-rw-r--r--packages/overlays/matrix-synapse/patches/0005-Log-policy-server-rejected-events.patch2
-rw-r--r--packages/overlays/matrix-synapse/patches/0006-Use-parse_boolean-for-unredacted-content.patch2
-rw-r--r--packages/overlays/matrix-synapse/patches/0007-Expose-tombstone-in-room-admin-api.patch2
-rw-r--r--packages/overlays/matrix-synapse/patches/0008-fix-Always-recheck-messages-pagination-data-if-a-bac.patch2
-rw-r--r--packages/overlays/matrix-synapse/patches/0009-Fix-pagination-with-large-gaps-of-rejected-events.patch2
-rw-r--r--packages/overlays/matrix-synapse/patches/0010-Fix-nix-flake.patch2
-rw-r--r--packages/overlays/matrix-synapse/patches/0011-Fix-gitignore-to-ignore-.venv.patch2
-rw-r--r--packages/overlays/matrix-synapse/patches/0012-Devenv-use-postgres-17.patch24
-rw-r--r--packages/overlays/matrix-synapse/patches/0013-RequestRatelimiter-expose-can_do_action.patch95
-rw-r--r--packages/overlays/matrix-synapse/patches/0014-Add-bulk-send-events-endpoint.patch187
15 files changed, 318 insertions, 12 deletions
diff --git a/host/Rory-ovh/services/containers/shared.nix b/host/Rory-ovh/services/containers/shared.nix

index fb1d13b..7bad188 100644 --- a/host/Rory-ovh/services/containers/shared.nix +++ b/host/Rory-ovh/services/containers/shared.nix
@@ -1,4 +1,4 @@ -{ pkgs, lib, ... }: +{ pkgs, lib, config, ... }: { environment.systemPackages = with pkgs; [ neofetch diff --git a/packages/overlays/matrix-synapse/patches/0001-Fast-auth-links.patch b/packages/overlays/matrix-synapse/patches/0001-Fast-auth-links.patch
index 0d92e4e..7b91953 100644 --- a/packages/overlays/matrix-synapse/patches/0001-Fast-auth-links.patch +++ b/packages/overlays/matrix-synapse/patches/0001-Fast-auth-links.patch
@@ -1,7 +1,7 @@ From 1b82f35b613e96c56bf18015e33f34328ad73188 Mon Sep 17 00:00:00 2001 From: Rory& <root@rory.gay> Date: Tue, 22 Jul 2025 05:07:01 +0200 -Subject: [PATCH 01/11] Fast auth links +Subject: [PATCH 01/14] Fast auth links --- synapse/storage/database.py | 43 +++++++++++++++++++ diff --git a/packages/overlays/matrix-synapse/patches/0002-Hotfix-ignore-rejected-events-in-delayed_events.patch b/packages/overlays/matrix-synapse/patches/0002-Hotfix-ignore-rejected-events-in-delayed_events.patch
index 3d5ea60..adc1b50 100644 --- a/packages/overlays/matrix-synapse/patches/0002-Hotfix-ignore-rejected-events-in-delayed_events.patch +++ b/packages/overlays/matrix-synapse/patches/0002-Hotfix-ignore-rejected-events-in-delayed_events.patch
@@ -1,7 +1,7 @@ From 346fb5899fa42d4604b7bf0261c5e1774e6d2c04 Mon Sep 17 00:00:00 2001 From: Rory& <root@rory.gay> Date: Sun, 20 Apr 2025 00:30:29 +0200 -Subject: [PATCH 02/11] Hotfix: ignore rejected events in delayed_events +Subject: [PATCH 02/14] Hotfix: ignore rejected events in delayed_events --- synapse/handlers/delayed_events.py | 7 ++++++- diff --git a/packages/overlays/matrix-synapse/patches/0003-Add-too-much-logging-to-room-summary-over-federation.patch b/packages/overlays/matrix-synapse/patches/0003-Add-too-much-logging-to-room-summary-over-federation.patch
index 5f4e596..c5a71ec 100644 --- a/packages/overlays/matrix-synapse/patches/0003-Add-too-much-logging-to-room-summary-over-federation.patch +++ b/packages/overlays/matrix-synapse/patches/0003-Add-too-much-logging-to-room-summary-over-federation.patch
@@ -1,7 +1,7 @@ From 929d1e329ec26d2e351591206a82c6e235660437 Mon Sep 17 00:00:00 2001 From: Rory& <root@rory.gay> Date: Wed, 23 Apr 2025 17:53:52 +0200 -Subject: [PATCH 03/11] Add too much logging to room summary over federation +Subject: [PATCH 03/14] Add too much logging to room summary over federation Signed-off-by: Rory& <root@rory.gay> --- diff --git a/packages/overlays/matrix-synapse/patches/0004-Log-entire-room-if-accessibility-check-fails.patch b/packages/overlays/matrix-synapse/patches/0004-Log-entire-room-if-accessibility-check-fails.patch
index 290f0da..04c00c1 100644 --- a/packages/overlays/matrix-synapse/patches/0004-Log-entire-room-if-accessibility-check-fails.patch +++ b/packages/overlays/matrix-synapse/patches/0004-Log-entire-room-if-accessibility-check-fails.patch
@@ -1,7 +1,7 @@ From 0ce933278f77e272e2cc894229a1178e1b4fb552 Mon Sep 17 00:00:00 2001 From: Rory& <root@rory.gay> Date: Wed, 23 Apr 2025 18:24:57 +0200 -Subject: [PATCH 04/11] Log entire room if accessibility check fails +Subject: [PATCH 04/14] Log entire room if accessibility check fails Signed-off-by: Rory& <root@rory.gay> --- diff --git a/packages/overlays/matrix-synapse/patches/0005-Log-policy-server-rejected-events.patch b/packages/overlays/matrix-synapse/patches/0005-Log-policy-server-rejected-events.patch
index ae59e63..7c6b002 100644 --- a/packages/overlays/matrix-synapse/patches/0005-Log-policy-server-rejected-events.patch +++ b/packages/overlays/matrix-synapse/patches/0005-Log-policy-server-rejected-events.patch
@@ -1,7 +1,7 @@ From 0b5d4c8104bf25f7bbb4e4e7db229742f04199b6 Mon Sep 17 00:00:00 2001 From: Rory& <root@rory.gay> Date: Tue, 27 May 2025 05:21:46 +0200 -Subject: [PATCH 05/11] Log policy server rejected events +Subject: [PATCH 05/14] Log policy server rejected events --- synapse/handlers/room_policy.py | 7 +++++++ diff --git a/packages/overlays/matrix-synapse/patches/0006-Use-parse_boolean-for-unredacted-content.patch b/packages/overlays/matrix-synapse/patches/0006-Use-parse_boolean-for-unredacted-content.patch
index 1c2841c..45fbd2c 100644 --- a/packages/overlays/matrix-synapse/patches/0006-Use-parse_boolean-for-unredacted-content.patch +++ b/packages/overlays/matrix-synapse/patches/0006-Use-parse_boolean-for-unredacted-content.patch
@@ -1,7 +1,7 @@ From 07d72fd39ea3044577322647d5ed1dd8cb6f77d9 Mon Sep 17 00:00:00 2001 From: Rory& <root@rory.gay> Date: Tue, 27 May 2025 06:14:26 +0200 -Subject: [PATCH 06/11] Use parse_boolean for unredacted content +Subject: [PATCH 06/14] Use parse_boolean for unredacted content --- synapse/rest/client/room.py | 5 ++--- diff --git a/packages/overlays/matrix-synapse/patches/0007-Expose-tombstone-in-room-admin-api.patch b/packages/overlays/matrix-synapse/patches/0007-Expose-tombstone-in-room-admin-api.patch
index 719705e..f331512 100644 --- a/packages/overlays/matrix-synapse/patches/0007-Expose-tombstone-in-room-admin-api.patch +++ b/packages/overlays/matrix-synapse/patches/0007-Expose-tombstone-in-room-admin-api.patch
@@ -1,7 +1,7 @@ From d3edb4aa9a225f521fdbc406c187fd40343b3963 Mon Sep 17 00:00:00 2001 From: Rory& <root@rory.gay> Date: Tue, 27 May 2025 06:37:52 +0200 -Subject: [PATCH 07/11] Expose tombstone in room admin api +Subject: [PATCH 07/14] Expose tombstone in room admin api --- synapse/rest/admin/rooms.py | 5 ++++ diff --git a/packages/overlays/matrix-synapse/patches/0008-fix-Always-recheck-messages-pagination-data-if-a-bac.patch b/packages/overlays/matrix-synapse/patches/0008-fix-Always-recheck-messages-pagination-data-if-a-bac.patch
index 363204e..724c134 100644 --- a/packages/overlays/matrix-synapse/patches/0008-fix-Always-recheck-messages-pagination-data-if-a-bac.patch +++ b/packages/overlays/matrix-synapse/patches/0008-fix-Always-recheck-messages-pagination-data-if-a-bac.patch
@@ -1,7 +1,7 @@ From afecddceaa6ece4cf797ce27e226a99acb8e8a6d Mon Sep 17 00:00:00 2001 From: Jason Little <j.little@famedly.com> Date: Wed, 30 Apr 2025 09:29:42 -0500 -Subject: [PATCH 08/11] fix: Always recheck `/messages` pagination data if a +Subject: [PATCH 08/14] fix: Always recheck `/messages` pagination data if a backfill might have been needed (#28) --- diff --git a/packages/overlays/matrix-synapse/patches/0009-Fix-pagination-with-large-gaps-of-rejected-events.patch b/packages/overlays/matrix-synapse/patches/0009-Fix-pagination-with-large-gaps-of-rejected-events.patch
index ebed62e..e249252 100644 --- a/packages/overlays/matrix-synapse/patches/0009-Fix-pagination-with-large-gaps-of-rejected-events.patch +++ b/packages/overlays/matrix-synapse/patches/0009-Fix-pagination-with-large-gaps-of-rejected-events.patch
@@ -1,7 +1,7 @@ From 2f2dd65326b8a8dc6b7ac99dbe7476abb2163469 Mon Sep 17 00:00:00 2001 From: Nicolas Werner <nicolas.werner@hotmail.de> Date: Sun, 8 Jun 2025 23:14:31 +0200 -Subject: [PATCH 09/11] Fix pagination with large gaps of rejected events +Subject: [PATCH 09/14] Fix pagination with large gaps of rejected events --- synapse/handlers/pagination.py | 13 +++++++++++-- diff --git a/packages/overlays/matrix-synapse/patches/0010-Fix-nix-flake.patch b/packages/overlays/matrix-synapse/patches/0010-Fix-nix-flake.patch
index 4df6090..a2bb1ed 100644 --- a/packages/overlays/matrix-synapse/patches/0010-Fix-nix-flake.patch +++ b/packages/overlays/matrix-synapse/patches/0010-Fix-nix-flake.patch
@@ -1,7 +1,7 @@ From 448de6ea7bfe1c6073726f517988e5deeb510861 Mon Sep 17 00:00:00 2001 From: Rory& <root@rory.gay> Date: Mon, 9 Jun 2025 17:38:34 +0200 -Subject: [PATCH 10/11] Fix nix flake +Subject: [PATCH 10/14] Fix nix flake --- flake.lock | 58 +++++++++++++++++++----------------------------------- diff --git a/packages/overlays/matrix-synapse/patches/0011-Fix-gitignore-to-ignore-.venv.patch b/packages/overlays/matrix-synapse/patches/0011-Fix-gitignore-to-ignore-.venv.patch
index 82335db..f627abc 100644 --- a/packages/overlays/matrix-synapse/patches/0011-Fix-gitignore-to-ignore-.venv.patch +++ b/packages/overlays/matrix-synapse/patches/0011-Fix-gitignore-to-ignore-.venv.patch
@@ -1,7 +1,7 @@ From e1b50954048039a23c538cd260644ccc63d82941 Mon Sep 17 00:00:00 2001 From: Rory& <root@rory.gay> Date: Mon, 9 Jun 2025 17:46:10 +0200 -Subject: [PATCH 11/11] Fix gitignore to ignore .venv +Subject: [PATCH 11/14] Fix gitignore to ignore .venv --- .gitignore | 1 + diff --git a/packages/overlays/matrix-synapse/patches/0012-Devenv-use-postgres-17.patch b/packages/overlays/matrix-synapse/patches/0012-Devenv-use-postgres-17.patch new file mode 100644
index 0000000..0e78105 --- /dev/null +++ b/packages/overlays/matrix-synapse/patches/0012-Devenv-use-postgres-17.patch
@@ -0,0 +1,24 @@ +From 8fefc1ece0f73ab4e4867cbb4cc1511dc7faa56f Mon Sep 17 00:00:00 2001 +From: Rory& <root@rory.gay> +Date: Fri, 25 Jul 2025 08:25:28 +0200 +Subject: [PATCH 12/14] Devenv: use postgres 17 + +--- + flake.nix | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/flake.nix b/flake.nix +index 76b3c1a4b0..cc41490a41 100644 +--- a/flake.nix ++++ b/flake.nix +@@ -157,6 +157,7 @@ + # Postgres is needed to run Synapse with postgres support and + # to run certain unit tests that require postgres. + services.postgres.enable = true; ++ services.postgres.package = pkgs.postgresql_17; + + # On the first invocation of `devenv up`, create a database for + # Synapse to store data in. +-- +2.49.0 + diff --git a/packages/overlays/matrix-synapse/patches/0013-RequestRatelimiter-expose-can_do_action.patch b/packages/overlays/matrix-synapse/patches/0013-RequestRatelimiter-expose-can_do_action.patch new file mode 100644
index 0000000..2ad8e55 --- /dev/null +++ b/packages/overlays/matrix-synapse/patches/0013-RequestRatelimiter-expose-can_do_action.patch
@@ -0,0 +1,95 @@ +From 4b62d4e914d8ff7e21bcfbbc6572f1f2a363e066 Mon Sep 17 00:00:00 2001 +From: Rory& <root@rory.gay> +Date: Fri, 25 Jul 2025 08:26:15 +0200 +Subject: [PATCH 13/14] RequestRatelimiter: expose can_do_action + +--- + synapse/api/ratelimiting.py | 75 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 75 insertions(+) + +diff --git a/synapse/api/ratelimiting.py b/synapse/api/ratelimiting.py +index 509ef6b2c1..5f22089a6b 100644 +--- a/synapse/api/ratelimiting.py ++++ b/synapse/api/ratelimiting.py +@@ -435,3 +435,78 @@ class RequestRatelimiter: + update=update, + n_actions=n_actions, + ) ++ ++ async def can_do_action( ++ self, ++ requester: Optional[Requester], ++ burst_count: Optional[int] = None, ++ update: bool = True, ++ is_admin_redaction: bool = False, ++ n_actions: int = 1, ++ ) -> Tuple[bool, float]: ++ """Can the entity (e.g. user or IP address) perform the action? ++ ++ Checks if the user has ratelimiting disabled in the database by looking ++ for null/zero values in the `ratelimit_override` table. (Non-zero ++ values aren't honoured, as they're specific to the event sending ++ ratelimiter, rather than all ratelimiters) ++ ++ Args: ++ requester: The requester that is doing the action, if any. Used to check ++ if the user has ratelimits disabled in the database. ++ key: An arbitrary key used to classify an action. Defaults to the ++ requester's user ID. ++ rate_hz: The long term number of actions that can be performed in a second. ++ Overrides the value set during instantiation if set. ++ burst_count: How many actions that can be performed before being limited. ++ Overrides the value set during instantiation if set. ++ update: Whether to count this check as performing the action. If the action ++ cannot be performed, the user's action count is not incremented at all. ++ n_actions: The number of times the user wants to do this action. If the user ++ cannot do all of the actions, the user's action count is not incremented ++ at all. ++ _time_now_s: The current time. Optional, defaults to the current time according ++ to self.clock. Only used by tests. ++ ++ Returns: ++ A tuple containing: ++ * A bool indicating if they can perform the action now ++ * The reactor timestamp for when the action can be performed next. ++ -1 if rate_hz is less than or equal to zero ++ """ ++ user_id = requester.user.to_string() ++ ++ # The AS user itself is never rate limited. ++ app_service = self.store.get_app_service_by_user_id(user_id) ++ if app_service is not None: ++ return True, 0 # do not ratelimit app service senders ++ ++ messages_per_second = self._rc_message.per_second ++ burst_count = self._rc_message.burst_count ++ ++ # Check if there is a per user override in the DB. ++ override = await self.store.get_ratelimit_for_user(user_id) ++ if override: ++ # If overridden with a null Hz then ratelimiting has been entirely ++ # disabled for the user ++ if not override.messages_per_second: ++ return True, 0 ++ ++ messages_per_second = override.messages_per_second ++ burst_count = override.burst_count ++ ++ if is_admin_redaction and self.admin_redaction_ratelimiter: ++ # If we have separate config for admin redactions, use a separate ++ # ratelimiter as to not have user_ids clash ++ return await self.admin_redaction_ratelimiter.can_do_action( ++ requester, update=update, n_actions=n_actions ++ ) ++ else: ++ # Override rate and burst count per-user ++ return await self.request_ratelimiter.can_do_action( ++ requester, ++ rate_hz=messages_per_second, ++ burst_count=burst_count, ++ update=update, ++ n_actions=n_actions, ++ ) +-- +2.49.0 + diff --git a/packages/overlays/matrix-synapse/patches/0014-Add-bulk-send-events-endpoint.patch b/packages/overlays/matrix-synapse/patches/0014-Add-bulk-send-events-endpoint.patch new file mode 100644
index 0000000..fdd6030 --- /dev/null +++ b/packages/overlays/matrix-synapse/patches/0014-Add-bulk-send-events-endpoint.patch
@@ -0,0 +1,187 @@ +From 452f38800dd00b8686543099d6a085f9b4210687 Mon Sep 17 00:00:00 2001 +From: Rory& <root@rory.gay> +Date: Sat, 26 Jul 2025 09:50:56 +0200 +Subject: [PATCH 14/14] Add bulk send events endpoint + +--- + synapse/rest/client/capabilities.py | 3 + + synapse/rest/client/room.py | 117 +++++++++++++++++++++++++++- + 2 files changed, 119 insertions(+), 1 deletion(-) + +diff --git a/synapse/rest/client/capabilities.py b/synapse/rest/client/capabilities.py +index 8f3193fb47..7220b75006 100644 +--- a/synapse/rest/client/capabilities.py ++++ b/synapse/rest/client/capabilities.py +@@ -74,6 +74,9 @@ class CapabilitiesRestServlet(RestServlet): + "m.get_login_token": { + "enabled": self.config.auth.login_via_existing_enabled, + }, ++ "gay.rory.bulk_send_events": { ++ "enabled": True ++ } + } + } + +diff --git a/synapse/rest/client/room.py b/synapse/rest/client/room.py +index f61152c35b..19ba13dd64 100644 +--- a/synapse/rest/client/room.py ++++ b/synapse/rest/client/room.py +@@ -23,10 +23,12 @@ + + import logging + import re ++import ijson + from enum import Enum + from http import HTTPStatus + from typing import TYPE_CHECKING, Awaitable, Dict, List, Optional, Tuple + from urllib import parse as urlparse ++from twisted.internet import defer + + from prometheus_client.core import Histogram + +@@ -44,6 +46,7 @@ from synapse.api.errors import ( + UnredactedContentDeletedError, + ) + from synapse.api.filtering import Filter ++from synapse.events import EventBase + from synapse.events.utils import SerializeEventConfig, format_event_for_client_v2 + from synapse.http.server import HttpServer + from synapse.http.servlet import ( +@@ -469,7 +472,6 @@ class RoomSendEventRestServlet(TransactionRestServlet): + txn_id, + ) + +- + def _parse_request_delay( + request: SynapseRequest, + max_delay: Optional[int], +@@ -1610,6 +1612,118 @@ class RoomSummaryRestServlet(ResolveRoomIdMixin, RestServlet): + remote_room_hosts, + ) + ++class RoomBulkSendEventRestServlet(ResolveRoomIdMixin, RestServlet): ++ """ ++ Bulk send events to a room. ++ ++ This endpoint allows sending multiple events to a room in a single request, ++ avoiding event linearisation issues. ++ """ ++ ++ PATTERNS = ( ++ re.compile( ++ "^/_matrix/client/unstable/gay.rory.bulk_send_events" ++ "/rooms/(?P<room_identifier>[^/]*)/bulk_send_events$" ++ ), ++ ) ++ CATEGORY = "Event sending requests" ++ ++ def __init__(self, hs: "HomeServer"): ++ super().__init__(hs) ++ self._auth = hs.get_auth() ++ self._event_creation_handler = hs.get_event_creation_handler() ++ self._message_handler = hs.get_message_handler() ++ ++ async def on_POST( ++ self, request: SynapseRequest, room_identifier: str ++ ) -> Tuple[int, JsonDict]: ++ logger.warning("bulk_send_events: Got bulk send events request") ++ requester = await self._auth.get_user_by_req(request, allow_guest=False) ++ room_id, remote_room_hosts = await self.resolve_room_id(room_identifier) ++ ++ force_sync_interval = parse_integer(request, "force_sync_interval", default=250) ++ ++ current_state_events = await self._message_handler.get_state_events( ++ room_id=room_id, ++ requester=requester, ++ ) ++ ++ state_map = {(event["type"], event.get("state_key", "")): event.get("event_id") for event in current_state_events} ++ ++ events = ijson.items( ++ request.content, ++ "item" ++ ) ++ ++ i = 0 ++ unpersisted_events = [] ++ ++ for event_data in events: ++ current_index = i ++ i += 1 ++ logger.info("bulk_send_events: Processing event %d: %s", current_index, event_data) ++ ++ event_dict: JsonDict = { ++ "type": event_data.get("type"), ++ "content": event_data.get("content", {}), ++ "room_id": room_id, ++ "sender": requester.user.to_string(), ++ } ++ ++ if "state_key" in event_data: ++ event_dict["state_key"] = event_data["state_key"] ++ ++ # Explicitly handle rate limits in order to avoid compounding effects ++ awaiting_ratelimit = False ++ ratelimit_hit = False ++ while awaiting_ratelimit: ++ can_do_action, ratelimit_expiry = await self._event_creation_handler.request_ratelimiter.can_do_action(requester, update=False) ++ if not can_do_action: ++ # can_do_action returns an absolute timestamp, convert it to a relative time ++ time_to_sleep = ratelimit_expiry - self._event_creation_handler.request_ratelimiter.clock.time() ++ logger.warning("bulk_send_events: Got rate limited in bulk sending events, waiting %ds", time_to_sleep) ++ await self._event_creation_handler.request_ratelimiter.clock.sleep(time_to_sleep) ++ ratelimit_hit = True ++ else: ++ awaiting_ratelimit = False ++ await self._event_creation_handler.request_ratelimiter.can_do_action(requester, update=True) ++ ++ event, unpersisted_context = await self._event_creation_handler.create_event( ++ requester, ++ event_dict, ++ for_batch=True, ++ state_map=state_map, ++ ) ++ context = await unpersisted_context.persist(event) ++ ++ if event.is_state(): ++ prev_event = await self._event_creation_handler.deduplicate_state_event(event, context) ++ if prev_event is not None: ++ logger.info( ++ "Not bothering to persist state event %s duplicated by %s", ++ event.event_id, ++ prev_event.event_id, ++ ) ++ continue ++ else: ++ state_map[(event_dict["type"], event_dict["state_key"])] = event.event_id ++ logger.warning("bulk_send_events: Updated state_map!") ++ ++ unpersisted_events.append((event, context)) ++ logger.warning("bulk_send_events: Persisted event %d: %s", current_index, event) ++ ++ if ratelimit_hit or len(unpersisted_events) >= force_sync_interval: ++ logger.warning("bulk_send_events: Hit rate limit or max batch size, sending %d events", len(unpersisted_events)) ++ await self._event_creation_handler.handle_new_client_event(requester, unpersisted_events, ratelimit=False) ++ unpersisted_events = [] ++ ++ # Finalize any remaining unpersisted events ++ if(len(unpersisted_events) > 0): ++ await self._event_creation_handler.handle_new_client_event(requester, unpersisted_events, ratelimit=False) ++ unpersisted_events = [] ++ ++ return 200, {} ++ + + def register_servlets(hs: "HomeServer", http_server: HttpServer) -> None: + RoomStateEventRestServlet(hs).register(http_server) +@@ -1619,6 +1733,7 @@ def register_servlets(hs: "HomeServer", http_server: HttpServer) -> None: + JoinRoomAliasServlet(hs).register(http_server) + RoomMembershipRestServlet(hs).register(http_server) + RoomSendEventRestServlet(hs).register(http_server) ++ RoomBulkSendEventRestServlet(hs).register(http_server) + PublicRoomListRestServlet(hs).register(http_server) + RoomStateRestServlet(hs).register(http_server) + RoomRedactEventRestServlet(hs).register(http_server) +-- +2.49.0 +