Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit 57ba345

Browse files
authored
Merge pull request #5209 from matrix-org/erikj/reactions_base
Land basic reaction and edit support.
2 parents 3787133 + 0667105 commit 57ba345

File tree

14 files changed

+1439
-16
lines changed

14 files changed

+1439
-16
lines changed

changelog.d/5209.feature

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add experimental support for relations (aka reactions and edits).

synapse/api/constants.py

+8
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,11 @@ class UserTypes(object):
119119
"""
120120
SUPPORT = "support"
121121
ALL_USER_TYPES = (SUPPORT,)
122+
123+
124+
class RelationTypes(object):
125+
"""The types of relations known to this server.
126+
"""
127+
ANNOTATION = "m.annotation"
128+
REPLACES = "m.replaces"
129+
REFERENCES = "m.references"

synapse/config/server.py

+5
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,11 @@ def read_config(self, config):
101101
"block_non_admin_invites", False,
102102
)
103103

104+
# Whether to enable experimental MSC1849 (aka relations) support
105+
self.experimental_msc1849_support_enabled = config.get(
106+
"experimental_msc1849_support_enabled", False,
107+
)
108+
104109
# Options to control access by tracking MAU
105110
self.limit_usage_by_mau = config.get("limit_usage_by_mau", False)
106111
self.max_mau_value = 0

synapse/events/utils.py

+52-4
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
from twisted.internet import defer
2323

24-
from synapse.api.constants import EventTypes
24+
from synapse.api.constants import EventTypes, RelationTypes
2525
from synapse.util.async_helpers import yieldable_gather_results
2626

2727
from . import EventBase
@@ -324,8 +324,12 @@ class EventClientSerializer(object):
324324
"""
325325

326326
def __init__(self, hs):
327-
pass
327+
self.store = hs.get_datastore()
328+
self.experimental_msc1849_support_enabled = (
329+
hs.config.experimental_msc1849_support_enabled
330+
)
328331

332+
@defer.inlineCallbacks
329333
def serialize_event(self, event, time_now, **kwargs):
330334
"""Serializes a single event.
331335
@@ -337,8 +341,52 @@ def serialize_event(self, event, time_now, **kwargs):
337341
Returns:
338342
Deferred[dict]: The serialized event
339343
"""
340-
event = serialize_event(event, time_now, **kwargs)
341-
return defer.succeed(event)
344+
# To handle the case of presence events and the like
345+
if not isinstance(event, EventBase):
346+
defer.returnValue(event)
347+
348+
event_id = event.event_id
349+
serialized_event = serialize_event(event, time_now, **kwargs)
350+
351+
# If MSC1849 is enabled then we need to look if thre are any relations
352+
# we need to bundle in with the event
353+
if self.experimental_msc1849_support_enabled:
354+
annotations = yield self.store.get_aggregation_groups_for_event(
355+
event_id,
356+
)
357+
references = yield self.store.get_relations_for_event(
358+
event_id, RelationTypes.REFERENCES, direction="f",
359+
)
360+
361+
if annotations.chunk:
362+
r = serialized_event["unsigned"].setdefault("m.relations", {})
363+
r[RelationTypes.ANNOTATION] = annotations.to_dict()
364+
365+
if references.chunk:
366+
r = serialized_event["unsigned"].setdefault("m.relations", {})
367+
r[RelationTypes.REFERENCES] = references.to_dict()
368+
369+
edit = None
370+
if event.type == EventTypes.Message:
371+
edit = yield self.store.get_applicable_edit(event_id)
372+
373+
if edit:
374+
# If there is an edit replace the content, preserving existing
375+
# relations.
376+
377+
relations = event.content.get("m.relates_to")
378+
serialized_event["content"] = edit.content.get("m.new_content", {})
379+
if relations:
380+
serialized_event["content"]["m.relates_to"] = relations
381+
else:
382+
serialized_event["content"].pop("m.relates_to", None)
383+
384+
r = serialized_event["unsigned"].setdefault("m.relations", {})
385+
r[RelationTypes.REPLACES] = {
386+
"event_id": edit.event_id,
387+
}
388+
389+
defer.returnValue(serialized_event)
342390

343391
def serialize_events(self, events, time_now, **kwargs):
344392
"""Serializes multiple events.

synapse/replication/slave/storage/events.py

+11-3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from synapse.storage.event_federation import EventFederationWorkerStore
2424
from synapse.storage.event_push_actions import EventPushActionsWorkerStore
2525
from synapse.storage.events_worker import EventsWorkerStore
26+
from synapse.storage.relations import RelationsWorkerStore
2627
from synapse.storage.roommember import RoomMemberWorkerStore
2728
from synapse.storage.signatures import SignatureWorkerStore
2829
from synapse.storage.state import StateGroupWorkerStore
@@ -52,6 +53,7 @@ class SlavedEventStore(EventFederationWorkerStore,
5253
EventsWorkerStore,
5354
SignatureWorkerStore,
5455
UserErasureWorkerStore,
56+
RelationsWorkerStore,
5557
BaseSlavedStore):
5658

5759
def __init__(self, db_conn, hs):
@@ -89,7 +91,7 @@ def process_replication_rows(self, stream_name, token, rows):
8991
for row in rows:
9092
self.invalidate_caches_for_event(
9193
-token, row.event_id, row.room_id, row.type, row.state_key,
92-
row.redacts,
94+
row.redacts, row.relates_to,
9395
backfilled=True,
9496
)
9597
return super(SlavedEventStore, self).process_replication_rows(
@@ -102,7 +104,7 @@ def _process_event_stream_row(self, token, row):
102104
if row.type == EventsStreamEventRow.TypeId:
103105
self.invalidate_caches_for_event(
104106
token, data.event_id, data.room_id, data.type, data.state_key,
105-
data.redacts,
107+
data.redacts, data.relates_to,
106108
backfilled=False,
107109
)
108110
elif row.type == EventsStreamCurrentStateRow.TypeId:
@@ -114,7 +116,8 @@ def _process_event_stream_row(self, token, row):
114116
raise Exception("Unknown events stream row type %s" % (row.type, ))
115117

116118
def invalidate_caches_for_event(self, stream_ordering, event_id, room_id,
117-
etype, state_key, redacts, backfilled):
119+
etype, state_key, redacts, relates_to,
120+
backfilled):
118121
self._invalidate_get_event_cache(event_id)
119122

120123
self.get_latest_event_ids_in_room.invalidate((room_id,))
@@ -136,3 +139,8 @@ def invalidate_caches_for_event(self, stream_ordering, event_id, room_id,
136139
state_key, stream_ordering
137140
)
138141
self.get_invited_rooms_for_user.invalidate((state_key,))
142+
143+
if relates_to:
144+
self.get_relations_for_event.invalidate_many((relates_to,))
145+
self.get_aggregation_groups_for_event.invalidate_many((relates_to,))
146+
self.get_applicable_edit.invalidate((relates_to,))

synapse/replication/tcp/streams/_base.py

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"type", # str
3333
"state_key", # str, optional
3434
"redacts", # str, optional
35+
"relates_to", # str, optional
3536
))
3637
PresenceStreamRow = namedtuple("PresenceStreamRow", (
3738
"user_id", # str

synapse/replication/tcp/streams/events.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,12 @@ def from_data(cls, data):
8080
class EventsStreamEventRow(BaseEventsStreamRow):
8181
TypeId = "ev"
8282

83-
event_id = attr.ib() # str
84-
room_id = attr.ib() # str
85-
type = attr.ib() # str
86-
state_key = attr.ib() # str, optional
87-
redacts = attr.ib() # str, optional
83+
event_id = attr.ib() # str
84+
room_id = attr.ib() # str
85+
type = attr.ib() # str
86+
state_key = attr.ib() # str, optional
87+
redacts = attr.ib() # str, optional
88+
relates_to = attr.ib() # str, optional
8889

8990

9091
@attr.s(slots=True, frozen=True)

synapse/rest/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
read_marker,
4545
receipts,
4646
register,
47+
relations,
4748
report_event,
4849
room_keys,
4950
room_upgrade_rest_servlet,
@@ -115,6 +116,7 @@ def register_servlets(client_resource, hs):
115116
room_upgrade_rest_servlet.register_servlets(hs, client_resource)
116117
capabilities.register_servlets(hs, client_resource)
117118
account_validity.register_servlets(hs, client_resource)
119+
relations.register_servlets(hs, client_resource)
118120

119121
# moving to /_synapse/admin
120122
synapse.rest.admin.register_servlets_for_client_rest_resource(

0 commit comments

Comments
 (0)