-
Notifications
You must be signed in to change notification settings - Fork 349
Return some room data in Sliding Sync /sync
#17320
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 20 commits
079194c
3e0f759
5e2fd4e
8ce06f1
aa5f54a
5c175d5
9089bfe
9427991
19b2297
81d36f3
9791209
70ecd4d
71eabe5
39b4f10
9883b0f
1c06153
57ba033
c81f300
d801db0
6942b64
884b448
0eb0294
b1b4231
87fac19
0e71a2f
21ca02c
3568311
7aea406
e3e431f
303d834
4c22131
83d6f76
fbd92e1
6c791a8
27d74b0
fb8fbd4
d91aa00
daa7e36
cccbd15
62c6a4e
39259f6
5c21315
c60aca7
11db1be
7395e10
2bf3923
ec2d8dc
0b9a903
48d0acf
2a944ff
8df39d1
b7914e7
7eb1806
935b98c
f163fcf
956f20e
830e09d
15fcead
81c06be
eb159c1
ba56350
f774032
325856e
63c7b50
1158058
32b8b68
6045e11
9e53336
a4263bf
10d78d6
0061561
b8687e7
7c9513c
8b73185
126ce1e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Add `rooms` data to experimental [MSC3575](https://github.com/matrix-org/matrix-spec-proposals/pull/3575) Sliding Sync `/sync` endpoint. | ||
MadLittleMods marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CI keeps failing on building debs. It's unclear what's even going wrong or a change to cause this and I'm unable to merge with the failing status. It was building fine on the https://github.com/element-hq/synapse/actions/runs/9754628604/job/26922590117
If I run Local build output
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've just rerun this on develop and it looks like its broken there too There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for fixing up the deb build issues @erikjohnston! For the first one, the fact that it was building a wheel at all is the hint as it should be downloading one normally. For the second one, it makes more sense but if we expect a clean checkout for the Docker builds, it would be nice to remove things according to the |
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -761,7 +761,6 @@ class SlidingSyncRestServlet(RestServlet): | |
"lists": { | ||
"foo-list": { | ||
"ranges": [ [0, 99] ], | ||
"sort": [ "by_notification_level", "by_recency", "by_name" ], | ||
"required_state": [ | ||
["m.room.join_rules", ""], | ||
["m.room.history_visibility", ""], | ||
|
@@ -771,18 +770,13 @@ class SlidingSyncRestServlet(RestServlet): | |
"filters": { | ||
"is_dm": true | ||
}, | ||
"bump_event_types": [ "m.room.message", "m.room.encrypted" ], | ||
} | ||
}, | ||
// Room Subscriptions API | ||
"room_subscriptions": { | ||
"!sub1:bar": { | ||
"required_state": [ ["*","*"] ], | ||
"timeline_limit": 10, | ||
"include_old_rooms": { | ||
"timeline_limit": 1, | ||
"required_state": [ ["m.room.tombstone", ""], ["m.room.create", ""] ], | ||
} | ||
} | ||
}, | ||
// Extensions API | ||
|
@@ -791,7 +785,7 @@ class SlidingSyncRestServlet(RestServlet): | |
|
||
Response JSON:: | ||
{ | ||
"next_pos": "s58_224_0_13_10_1_1_16_0_1", | ||
"pos": "s58_224_0_13_10_1_1_16_0_1", | ||
"lists": { | ||
"foo-list": { | ||
"count": 1337, | ||
|
@@ -830,7 +824,8 @@ class SlidingSyncRestServlet(RestServlet): | |
"joined_count": 41, | ||
"invited_count": 1, | ||
"notification_count": 1, | ||
"highlight_count": 0 | ||
"highlight_count": 0, | ||
"num_live": 2" | ||
}, | ||
// rooms from list | ||
"!foo:bar": { | ||
|
@@ -855,7 +850,8 @@ class SlidingSyncRestServlet(RestServlet): | |
"joined_count": 4, | ||
"invited_count": 0, | ||
"notification_count": 54, | ||
"highlight_count": 3 | ||
"highlight_count": 3, | ||
"num_live": 1, | ||
}, | ||
// ... 99 more items | ||
}, | ||
|
@@ -871,10 +867,11 @@ def __init__(self, hs: "HomeServer"): | |
super().__init__() | ||
self.auth = hs.get_auth() | ||
self.store = hs.get_datastores().main | ||
self.clock = hs.get_clock() | ||
self.filtering = hs.get_filtering() | ||
self.sliding_sync_handler = hs.get_sliding_sync_handler() | ||
self.event_serializer = hs.get_event_client_serializer() | ||
|
||
# TODO: Update this to `on_GET` once we figure out how we want to handle params | ||
async def on_POST(self, request: SynapseRequest) -> Tuple[int, JsonDict]: | ||
requester = await self.auth.get_user_by_req(request, allow_guest=True) | ||
user = requester.user | ||
|
@@ -920,22 +917,25 @@ async def on_POST(self, request: SynapseRequest) -> Tuple[int, JsonDict]: | |
logger.info("Client has disconnected; not serializing response.") | ||
return 200, {} | ||
|
||
response_content = await self.encode_response(sliding_sync_results) | ||
response_content = await self.encode_response(requester, sliding_sync_results) | ||
|
||
return 200, response_content | ||
|
||
# TODO: Is there a better way to encode things? | ||
async def encode_response( | ||
self, | ||
requester: Requester, | ||
sliding_sync_result: SlidingSyncResult, | ||
) -> JsonDict: | ||
response: JsonDict = defaultdict(dict) | ||
|
||
response["next_pos"] = await sliding_sync_result.next_pos.to_string(self.store) | ||
response["pos"] = await sliding_sync_result.next_pos.to_string(self.store) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just updating this field to match the MSC3575. |
||
serialized_lists = self.encode_lists(sliding_sync_result.lists) | ||
if serialized_lists: | ||
response["lists"] = serialized_lists | ||
response["rooms"] = {} # TODO: sliding_sync_result.rooms | ||
response["rooms"] = await self.encode_rooms( | ||
requester, sliding_sync_result.rooms | ||
) | ||
response["extensions"] = {} # TODO: sliding_sync_result.extensions | ||
|
||
return response | ||
|
@@ -961,6 +961,75 @@ def encode_operation( | |
|
||
return serialized_lists | ||
|
||
async def encode_rooms( | ||
self, | ||
requester: Requester, | ||
rooms: Dict[str, SlidingSyncResult.RoomResult], | ||
) -> JsonDict: | ||
time_now = self.clock.time_msec() | ||
|
||
serialize_options = SerializeEventConfig( | ||
event_format=format_event_for_client_v2_without_room_id, | ||
requester=requester, | ||
) | ||
|
||
serialized_rooms = {} | ||
for room_id, room_result in rooms.items(): | ||
serialized_timeline = await self.event_serializer.serialize_events( | ||
room_result.timeline_events, | ||
time_now, | ||
config=serialize_options, | ||
bundle_aggregations=room_result.bundled_aggregations, | ||
) | ||
|
||
serialized_required_state = await self.event_serializer.serialize_events( | ||
room_result.required_state, | ||
time_now, | ||
config=serialize_options, | ||
) | ||
|
||
serialized_rooms[room_id] = { | ||
"required_state": serialized_required_state, | ||
"timeline": serialized_timeline, | ||
"prev_batch": await room_result.prev_batch.to_string(self.store), | ||
"limited": room_result.limited, | ||
"joined_count": room_result.joined_count, | ||
"invited_count": room_result.invited_count, | ||
"notification_count": room_result.notification_count, | ||
"highlight_count": room_result.highlight_count, | ||
"num_live": room_result.num_live, | ||
} | ||
|
||
if room_result.name: | ||
serialized_rooms[room_id]["name"] = room_result.name | ||
|
||
if room_result.avatar: | ||
serialized_rooms[room_id]["avatar"] = room_result.avatar | ||
|
||
if room_result.heroes: | ||
serialized_rooms[room_id]["heroes"] = room_result.heroes | ||
|
||
# We should only include the `initial` key if it's `True` to save bandwidth. | ||
# The absense of this flag means `False`. | ||
if room_result.initial: | ||
serialized_rooms[room_id]["initial"] = room_result.initial | ||
|
||
# Field should be absent on non-DM rooms | ||
if room_result.is_dm: | ||
serialized_rooms[room_id]["is_dm"] = room_result.is_dm | ||
|
||
# Stripped state only applies to invite/knock rooms | ||
if room_result.stripped_state: | ||
# TODO: `knocked_state` but that isn't specced yet. | ||
# | ||
# TODO: Instead of adding `knocked_state`, it would be good to rename | ||
# this to `stripped_state` so it can be shared between invite and knock | ||
# rooms, see | ||
# https://github.com/matrix-org/matrix-spec-proposals/pull/3575#discussion_r1117629919 | ||
serialized_rooms[room_id]["invite_state"] = room_result.stripped_state | ||
|
||
return serialized_rooms | ||
|
||
|
||
def register_servlets(hs: "HomeServer", http_server: HttpServer) -> None: | ||
SyncRestServlet(hs).register(http_server) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,7 +31,8 @@ | |
from pydantic import Extra | ||
|
||
from synapse.events import EventBase | ||
from synapse.types import JsonMapping, StreamToken, UserID | ||
from synapse.handlers.relations import BundledAggregations | ||
MadLittleMods marked this conversation as resolved.
Show resolved
Hide resolved
|
||
from synapse.types import JsonDict, JsonMapping, StreamToken, UserID | ||
from synapse.types.rest.client import SlidingSyncBody | ||
|
||
|
||
|
@@ -159,11 +160,16 @@ class RoomResult: | |
entirely and NOT send "initial":false as this is wasteful on bandwidth. The | ||
absence of this flag means 'false'. | ||
required_state: The current state of the room | ||
timeline: Latest events in the room. The last event is the most recent | ||
timeline: Latest events in the room. The last event is the most recent. | ||
bundled_aggregations: A mapping of event ID to the bundled aggregations for | ||
the timeline events above. This allows clients to show accurate reaction | ||
counts (or edits, threads), even if some of the reaction events were skipped | ||
over in a gappy sync. | ||
is_dm: Flag to specify whether the room is a direct-message room (most likely | ||
between two people). | ||
invite_state: Stripped state events. Same as `rooms.invite.$room_id.invite_state` | ||
in sync v2, absent on joined/left rooms | ||
stripped_state: Stripped state events (for rooms where the usre is | ||
invited/knocked). Same as `rooms.invite.$room_id.invite_state` in sync v2, | ||
absent on joined/left rooms | ||
prev_batch: A token that can be passed as a start parameter to the | ||
`/rooms/<room_id>/messages` API to retrieve earlier messages. | ||
limited: True if their are more events than fit between the given position and now. | ||
|
@@ -185,14 +191,15 @@ class RoomResult: | |
(with potentially other old events in the timeline). | ||
""" | ||
|
||
name: str | ||
name: Optional[str] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We're deciding to make |
||
avatar: Optional[str] | ||
heroes: Optional[List[EventBase]] | ||
initial: bool | ||
required_state: List[EventBase] | ||
timeline: List[EventBase] | ||
timeline_events: List[EventBase] | ||
bundled_aggregations: Optional[Dict[str, BundledAggregations]] | ||
is_dm: bool | ||
invite_state: List[EventBase] | ||
stripped_state: Optional[List[JsonDict]] | ||
prev_batch: StreamToken | ||
limited: bool | ||
joined_count: int | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -152,9 +152,6 @@ class CommonRoomParameters(RequestBodyModel): | |
anyway. | ||
timeline_limit: The maximum number of timeline events to return per response. | ||
(Max 1000 messages) | ||
include_old_rooms: Determines if `predecessor` rooms are included in the | ||
`rooms` response. The user MUST be joined to old rooms for them to show up | ||
in the response. | ||
""" | ||
|
||
class IncludeOldRooms(RequestBodyModel): | ||
|
@@ -167,7 +164,6 @@ class IncludeOldRooms(RequestBodyModel): | |
timeline_limit: int | ||
else: | ||
timeline_limit: conint(le=1000, strict=True) # type: ignore[valid-type] | ||
include_old_rooms: Optional[IncludeOldRooms] = None | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removing |
||
|
||
class SlidingSyncList(CommonRoomParameters): | ||
""" | ||
|
@@ -208,9 +204,6 @@ class SlidingSyncList(CommonRoomParameters): | |
} | ||
|
||
timeline_limit: The maximum number of timeline events to return per response. | ||
include_old_rooms: Determines if `predecessor` rooms are included in the | ||
`rooms` response. The user MUST be joined to old rooms for them to show up | ||
in the response. | ||
include_heroes: Return a stripped variant of membership events (containing | ||
`user_id` and optionally `avatar_url` and `displayname`) for the users used | ||
to calculate the room name. | ||
|
Uh oh!
There was an error while loading. Please reload this page.