Remove references to unstable identifiers from MSC3440. (#12382)

Removes references to unstable thread relation, unstable
identifiers for filtering parameters, and the experimental
config flag.
This commit is contained in:
Patrick Cloke 2022-04-12 08:42:03 -04:00 committed by GitHub
parent 1783156dbc
commit 86cf6a3a17
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 21 additions and 98 deletions

View file

@ -0,0 +1 @@
Remove unstable identifiers from [MSC3440](https://github.com/matrix-org/matrix-doc/pull/3440).

View file

@ -179,8 +179,6 @@ class RelationTypes:
REPLACE: Final = "m.replace" REPLACE: Final = "m.replace"
REFERENCE: Final = "m.reference" REFERENCE: Final = "m.reference"
THREAD: Final = "m.thread" THREAD: Final = "m.thread"
# TODO Remove this in Synapse >= v1.57.0.
UNSTABLE_THREAD: Final = "io.element.thread"
class LimitBlockingTypes: class LimitBlockingTypes:

View file

@ -89,9 +89,7 @@ ROOM_EVENT_FILTER_SCHEMA = {
"org.matrix.not_labels": {"type": "array", "items": {"type": "string"}}, "org.matrix.not_labels": {"type": "array", "items": {"type": "string"}},
# MSC3440, filtering by event relations. # MSC3440, filtering by event relations.
"related_by_senders": {"type": "array", "items": {"type": "string"}}, "related_by_senders": {"type": "array", "items": {"type": "string"}},
"io.element.relation_senders": {"type": "array", "items": {"type": "string"}},
"related_by_rel_types": {"type": "array", "items": {"type": "string"}}, "related_by_rel_types": {"type": "array", "items": {"type": "string"}},
"io.element.relation_types": {"type": "array", "items": {"type": "string"}},
}, },
} }
@ -323,16 +321,6 @@ class Filter:
self.related_by_senders = self.filter_json.get("related_by_senders", None) self.related_by_senders = self.filter_json.get("related_by_senders", None)
self.related_by_rel_types = self.filter_json.get("related_by_rel_types", None) self.related_by_rel_types = self.filter_json.get("related_by_rel_types", None)
# Fallback to the unstable prefix if the stable version is not given.
if hs.config.experimental.msc3440_enabled:
self.related_by_senders = self.related_by_senders or self.filter_json.get(
"io.element.relation_senders", None
)
self.related_by_rel_types = (
self.related_by_rel_types
or self.filter_json.get("io.element.relation_types", None)
)
def filters_all_types(self) -> bool: def filters_all_types(self) -> bool:
return "*" in self.not_types return "*" in self.not_types

View file

@ -26,9 +26,6 @@ class ExperimentalConfig(Config):
def read_config(self, config: JsonDict, **kwargs: Any) -> None: def read_config(self, config: JsonDict, **kwargs: Any) -> None:
experimental = config.get("experimental_features") or {} experimental = config.get("experimental_features") or {}
# MSC3440 (thread relation)
self.msc3440_enabled: bool = experimental.get("msc3440_enabled", False)
# MSC3026 (busy presence state) # MSC3026 (busy presence state)
self.msc3026_enabled: bool = experimental.get("msc3026_enabled", False) self.msc3026_enabled: bool = experimental.get("msc3026_enabled", False)

View file

@ -39,7 +39,6 @@ from . import EventBase
if TYPE_CHECKING: if TYPE_CHECKING:
from synapse.handlers.relations import BundledAggregations from synapse.handlers.relations import BundledAggregations
from synapse.server import HomeServer
# Split strings on "." but not "\." This uses a negative lookbehind assertion for '\' # Split strings on "." but not "\." This uses a negative lookbehind assertion for '\'
@ -396,9 +395,6 @@ class EventClientSerializer:
clients. clients.
""" """
def __init__(self, hs: "HomeServer"):
self._msc3440_enabled = hs.config.experimental.msc3440_enabled
def serialize_event( def serialize_event(
self, self,
event: Union[JsonDict, EventBase], event: Union[JsonDict, EventBase],
@ -525,8 +521,6 @@ class EventClientSerializer:
"current_user_participated": thread.current_user_participated, "current_user_participated": thread.current_user_participated,
} }
serialized_aggregations[RelationTypes.THREAD] = thread_summary serialized_aggregations[RelationTypes.THREAD] = thread_summary
if self._msc3440_enabled:
serialized_aggregations[RelationTypes.UNSTABLE_THREAD] = thread_summary
# Include the bundled aggregations in the event. # Include the bundled aggregations in the event.
if serialized_aggregations: if serialized_aggregations:

View file

@ -1102,10 +1102,7 @@ class EventCreationHandler:
raise SynapseError(400, "Can't send same reaction twice") raise SynapseError(400, "Can't send same reaction twice")
# Don't attempt to start a thread if the parent event is a relation. # Don't attempt to start a thread if the parent event is a relation.
elif ( elif relation_type == RelationTypes.THREAD:
relation_type == RelationTypes.THREAD
or relation_type == RelationTypes.UNSTABLE_THREAD
):
if await self.store.event_includes_relation(relates_to): if await self.store.event_includes_relation(relates_to):
raise SynapseError( raise SynapseError(
400, "Cannot start threads from an event with a relation" 400, "Cannot start threads from an event with a relation"

View file

@ -100,7 +100,6 @@ class VersionsRestServlet(RestServlet):
# Adds support for jump to date endpoints (/timestamp_to_event) as per MSC3030 # Adds support for jump to date endpoints (/timestamp_to_event) as per MSC3030
"org.matrix.msc3030": self.config.experimental.msc3030_enabled, "org.matrix.msc3030": self.config.experimental.msc3030_enabled,
# Adds support for thread relations, per MSC3440. # Adds support for thread relations, per MSC3440.
"org.matrix.msc3440": self.config.experimental.msc3440_enabled,
"org.matrix.msc3440.stable": True, # TODO: remove when "v1.3" is added above "org.matrix.msc3440.stable": True, # TODO: remove when "v1.3" is added above
}, },
}, },

View file

@ -758,7 +758,7 @@ class HomeServer(metaclass=abc.ABCMeta):
@cache_in_self @cache_in_self
def get_event_client_serializer(self) -> EventClientSerializer: def get_event_client_serializer(self) -> EventClientSerializer:
return EventClientSerializer(self) return EventClientSerializer()
@cache_in_self @cache_in_self
def get_password_policy_handler(self) -> PasswordPolicyHandler: def get_password_policy_handler(self) -> PasswordPolicyHandler:

View file

@ -1819,10 +1819,7 @@ class PersistEventsStore:
if rel_type == RelationTypes.REPLACE: if rel_type == RelationTypes.REPLACE:
txn.call_after(self.store.get_applicable_edit.invalidate, (parent_id,)) txn.call_after(self.store.get_applicable_edit.invalidate, (parent_id,))
if ( if rel_type == RelationTypes.THREAD:
rel_type == RelationTypes.THREAD
or rel_type == RelationTypes.UNSTABLE_THREAD
):
txn.call_after(self.store.get_thread_summary.invalidate, (parent_id,)) txn.call_after(self.store.get_thread_summary.invalidate, (parent_id,))
# It should be safe to only invalidate the cache if the user has not # It should be safe to only invalidate the cache if the user has not
# previously participated in the thread, but that's difficult (and # previously participated in the thread, but that's difficult (and

View file

@ -14,7 +14,6 @@
import logging import logging
from typing import ( from typing import (
TYPE_CHECKING,
Collection, Collection,
Dict, Dict,
FrozenSet, FrozenSet,
@ -32,20 +31,12 @@ import attr
from synapse.api.constants import RelationTypes from synapse.api.constants import RelationTypes
from synapse.events import EventBase from synapse.events import EventBase
from synapse.storage._base import SQLBaseStore from synapse.storage._base import SQLBaseStore
from synapse.storage.database import ( from synapse.storage.database import LoggingTransaction, make_in_list_sql_clause
DatabasePool,
LoggingDatabaseConnection,
LoggingTransaction,
make_in_list_sql_clause,
)
from synapse.storage.databases.main.stream import generate_pagination_where_clause from synapse.storage.databases.main.stream import generate_pagination_where_clause
from synapse.storage.engines import PostgresEngine from synapse.storage.engines import PostgresEngine
from synapse.types import JsonDict, RoomStreamToken, StreamToken from synapse.types import JsonDict, RoomStreamToken, StreamToken
from synapse.util.caches.descriptors import cached, cachedList from synapse.util.caches.descriptors import cached, cachedList
if TYPE_CHECKING:
from synapse.server import HomeServer
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -63,16 +54,6 @@ class _RelatedEvent:
class RelationsWorkerStore(SQLBaseStore): class RelationsWorkerStore(SQLBaseStore):
def __init__(
self,
database: DatabasePool,
db_conn: LoggingDatabaseConnection,
hs: "HomeServer",
):
super().__init__(database, db_conn, hs)
self._msc3440_enabled = hs.config.experimental.msc3440_enabled
@cached(uncached_args=("event",), tree=True) @cached(uncached_args=("event",), tree=True)
async def get_relations_for_event( async def get_relations_for_event(
self, self,
@ -497,7 +478,7 @@ class RelationsWorkerStore(SQLBaseStore):
AND parent.room_id = child.room_id AND parent.room_id = child.room_id
WHERE WHERE
%s %s
AND %s AND relation_type = ?
ORDER BY parent.event_id, child.topological_ordering DESC, child.stream_ordering DESC ORDER BY parent.event_id, child.topological_ordering DESC, child.stream_ordering DESC
""" """
else: else:
@ -512,22 +493,16 @@ class RelationsWorkerStore(SQLBaseStore):
AND parent.room_id = child.room_id AND parent.room_id = child.room_id
WHERE WHERE
%s %s
AND %s AND relation_type = ?
ORDER BY child.topological_ordering DESC, child.stream_ordering DESC ORDER BY child.topological_ordering DESC, child.stream_ordering DESC
""" """
clause, args = make_in_list_sql_clause( clause, args = make_in_list_sql_clause(
txn.database_engine, "relates_to_id", event_ids txn.database_engine, "relates_to_id", event_ids
) )
args.append(RelationTypes.THREAD)
if self._msc3440_enabled: txn.execute(sql % (clause,), args)
relations_clause = "(relation_type = ? OR relation_type = ?)"
args.extend((RelationTypes.THREAD, RelationTypes.UNSTABLE_THREAD))
else:
relations_clause = "relation_type = ?"
args.append(RelationTypes.THREAD)
txn.execute(sql % (clause, relations_clause), args)
latest_event_ids = {} latest_event_ids = {}
for parent_event_id, child_event_id in txn: for parent_event_id, child_event_id in txn:
# Only consider the latest threaded reply (by topological ordering). # Only consider the latest threaded reply (by topological ordering).
@ -547,7 +522,7 @@ class RelationsWorkerStore(SQLBaseStore):
AND parent.room_id = child.room_id AND parent.room_id = child.room_id
WHERE WHERE
%s %s
AND %s AND relation_type = ?
GROUP BY parent.event_id GROUP BY parent.event_id
""" """
@ -556,15 +531,9 @@ class RelationsWorkerStore(SQLBaseStore):
clause, args = make_in_list_sql_clause( clause, args = make_in_list_sql_clause(
txn.database_engine, "relates_to_id", latest_event_ids.keys() txn.database_engine, "relates_to_id", latest_event_ids.keys()
) )
args.append(RelationTypes.THREAD)
if self._msc3440_enabled: txn.execute(sql % (clause,), args)
relations_clause = "(relation_type = ? OR relation_type = ?)"
args.extend((RelationTypes.THREAD, RelationTypes.UNSTABLE_THREAD))
else:
relations_clause = "relation_type = ?"
args.append(RelationTypes.THREAD)
txn.execute(sql % (clause, relations_clause), args)
counts = dict(cast(List[Tuple[str, int]], txn.fetchall())) counts = dict(cast(List[Tuple[str, int]], txn.fetchall()))
return counts, latest_event_ids return counts, latest_event_ids
@ -622,7 +591,7 @@ class RelationsWorkerStore(SQLBaseStore):
parent.event_id = relates_to_id parent.event_id = relates_to_id
AND parent.room_id = child.room_id AND parent.room_id = child.room_id
WHERE WHERE
%s relation_type = ?
AND %s AND %s
AND %s AND %s
GROUP BY parent.event_id, child.sender GROUP BY parent.event_id, child.sender
@ -638,16 +607,9 @@ class RelationsWorkerStore(SQLBaseStore):
txn.database_engine, "relates_to_id", event_ids txn.database_engine, "relates_to_id", event_ids
) )
if self._msc3440_enabled:
relations_clause = "(relation_type = ? OR relation_type = ?)"
relations_args = [RelationTypes.THREAD, RelationTypes.UNSTABLE_THREAD]
else:
relations_clause = "relation_type = ?"
relations_args = [RelationTypes.THREAD]
txn.execute( txn.execute(
sql % (users_sql, events_clause, relations_clause), sql % (users_sql, events_clause),
users_args + events_args + relations_args, [RelationTypes.THREAD] + users_args + events_args,
) )
return {(row[0], row[1]): row[2] for row in txn} return {(row[0], row[1]): row[2] for row in txn}
@ -677,7 +639,7 @@ class RelationsWorkerStore(SQLBaseStore):
user participated in that event's thread, otherwise false. user participated in that event's thread, otherwise false.
""" """
def _get_thread_summary_txn(txn: LoggingTransaction) -> Set[str]: def _get_threads_participated_txn(txn: LoggingTransaction) -> Set[str]:
# Fetch whether the requester has participated or not. # Fetch whether the requester has participated or not.
sql = """ sql = """
SELECT DISTINCT relates_to_id SELECT DISTINCT relates_to_id
@ -688,28 +650,20 @@ class RelationsWorkerStore(SQLBaseStore):
AND parent.room_id = child.room_id AND parent.room_id = child.room_id
WHERE WHERE
%s %s
AND %s AND relation_type = ?
AND child.sender = ? AND child.sender = ?
""" """
clause, args = make_in_list_sql_clause( clause, args = make_in_list_sql_clause(
txn.database_engine, "relates_to_id", event_ids txn.database_engine, "relates_to_id", event_ids
) )
args.extend([RelationTypes.THREAD, user_id])
if self._msc3440_enabled: txn.execute(sql % (clause,), args)
relations_clause = "(relation_type = ? OR relation_type = ?)"
args.extend((RelationTypes.THREAD, RelationTypes.UNSTABLE_THREAD))
else:
relations_clause = "relation_type = ?"
args.append(RelationTypes.THREAD)
args.append(user_id)
txn.execute(sql % (clause, relations_clause), args)
return {row[0] for row in txn.fetchall()} return {row[0] for row in txn.fetchall()}
participated_threads = await self.db_pool.runInteraction( participated_threads = await self.db_pool.runInteraction(
"get_thread_summary", _get_thread_summary_txn "get_threads_participated", _get_threads_participated_txn
) )
return {event_id: event_id in participated_threads for event_id in event_ids} return {event_id: event_id in participated_threads for event_id in event_ids}

View file

@ -481,9 +481,7 @@ class FilteringTestCase(unittest.HomeserverTestCase):
# events). This is a bit cheeky, but tests the logic of _check_event_relations. # events). This is a bit cheeky, but tests the logic of _check_event_relations.
# Filter for a particular sender. # Filter for a particular sender.
definition = { definition = {"related_by_senders": ["@foo:bar"]}
"io.element.relation_senders": ["@foo:bar"],
}
async def events_have_relations(*args, **kwargs): async def events_have_relations(*args, **kwargs):
return ["$with_relation"] return ["$with_relation"]