diff --git a/synapse/app/generic_worker.py b/synapse/app/generic_worker.py
index bcc8abe20c..8108b1e98f 100644
--- a/synapse/app/generic_worker.py
+++ b/synapse/app/generic_worker.py
@@ -199,6 +199,9 @@ class GenericWorkerServer(HomeServer):
"A 'media' listener is configured but the media"
" repository is disabled. Ignoring."
)
+ elif name == "health":
+ # Skip loading, health resource is always included
+ continue
if name == "openid" and "federation" not in res.names:
# Only load the openid resource separately if federation resource
diff --git a/synapse/app/homeserver.py b/synapse/app/homeserver.py
index b9be558c7e..6176a70eb2 100644
--- a/synapse/app/homeserver.py
+++ b/synapse/app/homeserver.py
@@ -96,6 +96,9 @@ class SynapseHomeServer(HomeServer):
# Skip loading openid resource if federation is defined
# since federation resource will include openid
continue
+ if name == "health":
+ # Skip loading, health resource is always included
+ continue
resources.update(self._configure_named_resource(name, res.compress))
additional_resources = listener_config.http_options.additional_resources
diff --git a/synapse/config/_base.pyi b/synapse/config/_base.pyi
index bd265de536..b5cec132b4 100644
--- a/synapse/config/_base.pyi
+++ b/synapse/config/_base.pyi
@@ -1,5 +1,3 @@
-from __future__ import annotations
-
import argparse
from typing import (
Any,
@@ -20,7 +18,7 @@ from typing import (
import jinja2
-from synapse.config import (
+from synapse.config import ( # noqa: F401
account_validity,
api,
appservice,
@@ -169,7 +167,7 @@ class RootConfig:
self, section_name: Literal["caches"]
) -> cache.CacheConfig: ...
@overload
- def reload_config_section(self, section_name: str) -> Config: ...
+ def reload_config_section(self, section_name: str) -> "Config": ...
class Config:
root: RootConfig
@@ -202,9 +200,9 @@ def find_config_files(search_paths: List[str]) -> List[str]: ...
class ShardedWorkerHandlingConfig:
instances: List[str]
def __init__(self, instances: List[str]) -> None: ...
- def should_handle(self, instance_name: str, key: str) -> bool: ...
+ def should_handle(self, instance_name: str, key: str) -> bool: ... # noqa: F811
class RoutableShardedWorkerHandlingConfig(ShardedWorkerHandlingConfig):
- def get_instance(self, key: str) -> str: ...
+ def get_instance(self, key: str) -> str: ... # noqa: F811
def read_file(file_path: Any, config_path: Iterable[str]) -> str: ...
diff --git a/synapse/config/experimental.py b/synapse/config/experimental.py
index 0f3870bfe1..a8b2db372d 100644
--- a/synapse/config/experimental.py
+++ b/synapse/config/experimental.py
@@ -139,3 +139,6 @@ class ExperimentalConfig(Config):
# MSC3391: Removing account data.
self.msc3391_enabled = experimental.get("msc3391_enabled", False)
+
+ # MSC3925: do not replace events with their edits
+ self.msc3925_inhibit_edit = experimental.get("msc3925_inhibit_edit", False)
diff --git a/synapse/events/utils.py b/synapse/events/utils.py
index 13fa93afb8..ae57a4df5e 100644
--- a/synapse/events/utils.py
+++ b/synapse/events/utils.py
@@ -403,6 +403,14 @@ class EventClientSerializer:
clients.
"""
+ def __init__(self, inhibit_replacement_via_edits: bool = False):
+ """
+ Args:
+ inhibit_replacement_via_edits: If this is set to True, then events are
+ never replaced by their edits.
+ """
+ self._inhibit_replacement_via_edits = inhibit_replacement_via_edits
+
def serialize_event(
self,
event: Union[JsonDict, EventBase],
@@ -422,6 +430,8 @@ class EventClientSerializer:
into the event.
apply_edits: Whether the content of the event should be modified to reflect
any replacement in `bundle_aggregations[<event_id>].replace`.
+ See also the `inhibit_replacement_via_edits` constructor arg: if that is
+ set to True, then this argument is ignored.
Returns:
The serialized event
"""
@@ -495,7 +505,8 @@ class EventClientSerializer:
again for additional events in a recursive manner.
serialized_event: The serialized event which may be modified.
apply_edits: Whether the content of the event should be modified to reflect
- any replacement in `aggregations.replace`.
+ any replacement in `aggregations.replace` (subject to the
+ `inhibit_replacement_via_edits` constructor arg).
"""
# We have already checked that aggregations exist for this event.
@@ -518,15 +529,21 @@ class EventClientSerializer:
if event_aggregations.replace:
# If there is an edit, optionally apply it to the event.
edit = event_aggregations.replace
- if apply_edits:
+ if apply_edits and not self._inhibit_replacement_via_edits:
self._apply_edit(event, serialized_event, edit)
# Include information about it in the relations dict.
- serialized_aggregations[RelationTypes.REPLACE] = {
- "event_id": edit.event_id,
- "origin_server_ts": edit.origin_server_ts,
- "sender": edit.sender,
- }
+ #
+ # Matrix spec v1.5 (https://spec.matrix.org/v1.5/client-server-api/#server-side-aggregation-of-mreplace-relationships)
+ # said that we should only include the `event_id`, `origin_server_ts` and
+ # `sender` of the edit; however MSC3925 proposes extending it to the whole
+ # of the edit, which is what we do here.
+ serialized_aggregations[RelationTypes.REPLACE] = self.serialize_event(
+ edit,
+ time_now,
+ config=config,
+ apply_edits=False,
+ )
# Include any threaded replies to this event.
if event_aggregations.thread:
diff --git a/synapse/handlers/message.py b/synapse/handlers/message.py
index 88fc51a4c9..3278a695ed 100644
--- a/synapse/handlers/message.py
+++ b/synapse/handlers/message.py
@@ -1531,12 +1531,23 @@ class EventCreationHandler:
external federation senders don't have to recalculate it themselves.
"""
- for event, _ in events_and_context:
- if not self._external_cache.is_enabled():
- return
+ if not self._external_cache.is_enabled():
+ return
- # If external cache is enabled we should always have this.
- assert self._external_cache_joined_hosts_updates is not None
+ # If external cache is enabled we should always have this.
+ assert self._external_cache_joined_hosts_updates is not None
+
+ for event, event_context in events_and_context:
+ if event_context.partial_state:
+ # To populate the cache for a partial-state event, we either have to
+ # block until full state, which the code below does, or change the
+ # meaning of cache values to be the list of hosts to which we plan to
+ # send events and calculate that instead.
+ #
+ # The federation senders don't use the external cache when sending
+ # events in partial-state rooms anyway, so let's not bother populating
+ # the cache.
+ continue
# We actually store two mappings, event ID -> prev state group,
# state group -> joined hosts, which is much more space efficient
diff --git a/synapse/module_api/__init__.py b/synapse/module_api/__init__.py
index 6f4a934b05..6153a48257 100644
--- a/synapse/module_api/__init__.py
+++ b/synapse/module_api/__init__.py
@@ -1585,6 +1585,33 @@ class ModuleApi:
return room_id_and_alias["room_id"], room_id_and_alias.get("room_alias", None)
+ async def set_displayname(
+ self,
+ user_id: UserID,
+ new_displayname: str,
+ deactivation: bool = False,
+ ) -> None:
+ """Sets a user's display name.
+
+ Added in Synapse v1.76.0.
+
+ Args:
+ user_id:
+ The user whose display name is to be changed.
+ new_displayname:
+ The new display name to give the user.
+ deactivation:
+ Whether this change was made while deactivating the user.
+ """
+ requester = create_requester(user_id)
+ await self._hs.get_profile_handler().set_displayname(
+ target_user=user_id,
+ requester=requester,
+ new_displayname=new_displayname,
+ by_admin=True,
+ deactivation=deactivation,
+ )
+
class PublicRoomListManager:
"""Contains methods for adding to, removing from and querying whether a room
diff --git a/synapse/server.py b/synapse/server.py
index 5baae2325e..f4ab94c4f3 100644
--- a/synapse/server.py
+++ b/synapse/server.py
@@ -743,7 +743,7 @@ class HomeServer(metaclass=abc.ABCMeta):
@cache_in_self
def get_event_client_serializer(self) -> EventClientSerializer:
- return EventClientSerializer()
+ return EventClientSerializer(self.config.experimental.msc3925_inhibit_edit)
@cache_in_self
def get_password_policy_handler(self) -> PasswordPolicyHandler:
diff --git a/synapse/storage/databases/main/events_bg_updates.py b/synapse/storage/databases/main/events_bg_updates.py
index 9e31798ab1..b9d3c36d60 100644
--- a/synapse/storage/databases/main/events_bg_updates.py
+++ b/synapse/storage/databases/main/events_bg_updates.py
@@ -69,6 +69,8 @@ class _BackgroundUpdates:
EVENTS_POPULATE_STATE_KEY_REJECTIONS = "events_populate_state_key_rejections"
+ EVENTS_JUMP_TO_DATE_INDEX = "events_jump_to_date_index"
+
@attr.s(slots=True, frozen=True, auto_attribs=True)
class _CalculateChainCover:
@@ -260,6 +262,16 @@ class EventsBackgroundUpdatesStore(SQLBaseStore):
self._background_events_populate_state_key_rejections,
)
+ # Add an index that would be useful for jumping to date using
+ # get_event_id_for_timestamp.
+ self.db_pool.updates.register_background_index_update(
+ _BackgroundUpdates.EVENTS_JUMP_TO_DATE_INDEX,
+ index_name="events_jump_to_date_idx",
+ table="events",
+ columns=["room_id", "origin_server_ts"],
+ where_clause="NOT outlier",
+ )
+
async def _background_reindex_fields_sender(
self, progress: JsonDict, batch_size: int
) -> int:
diff --git a/synapse/storage/schema/main/delta/73/24_events_jump_to_date_index.sql b/synapse/storage/schema/main/delta/73/24_events_jump_to_date_index.sql
new file mode 100644
index 0000000000..67059909a1
--- /dev/null
+++ b/synapse/storage/schema/main/delta/73/24_events_jump_to_date_index.sql
@@ -0,0 +1,17 @@
+/* Copyright 2023 The Matrix.org Foundation C.I.C
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+INSERT INTO background_updates (ordering, update_name, progress_json) VALUES
+ (7324, 'events_jump_to_date_index', '{}');
|