54
54
logger = logging .getLogger (__name__ )
55
55
56
56
57
+ # The event types that clients should consider as new activity.
58
+ DEFAULT_BUMP_EVENT_TYPES = {
59
+ EventTypes .Message ,
60
+ EventTypes .Encrypted ,
61
+ EventTypes .Sticker ,
62
+ EventTypes .CallInvite ,
63
+ EventTypes .PollStart ,
64
+ EventTypes .LiveLocationShareStart ,
65
+ }
66
+
67
+
57
68
def filter_membership_for_sync (
58
69
* , membership : str , user_id : str , sender : Optional [str ]
59
70
) -> bool :
@@ -285,6 +296,7 @@ class _RoomMembershipForUser:
285
296
range
286
297
"""
287
298
299
+ room_id : str
288
300
event_id : Optional [str ]
289
301
event_pos : PersistedEventPosition
290
302
membership : str
@@ -469,7 +481,9 @@ async def current_sync_for_user(
469
481
#
470
482
# Both sides of range are inclusive so we `+ 1`
471
483
max_num_rooms = range [1 ] - range [0 ] + 1
472
- for room_id , _ in sorted_room_info [range [0 ] :]:
484
+ for room_membership in sorted_room_info [range [0 ] :]:
485
+ room_id = room_membership .room_id
486
+
473
487
if len (room_ids_in_list ) >= max_num_rooms :
474
488
break
475
489
@@ -519,7 +533,7 @@ async def current_sync_for_user(
519
533
user = sync_config .user ,
520
534
room_id = room_id ,
521
535
room_sync_config = room_sync_config ,
522
- rooms_membership_for_user_at_to_token = sync_room_map [room_id ],
536
+ room_membership_for_user_at_to_token = sync_room_map [room_id ],
523
537
from_token = from_token ,
524
538
to_token = to_token ,
525
539
)
@@ -591,6 +605,7 @@ async def get_sync_room_ids_for_user(
591
605
# (below) because they are potentially from the current snapshot time
592
606
# instead from the time of the `to_token`.
593
607
room_for_user .room_id : _RoomMembershipForUser (
608
+ room_id = room_for_user .room_id ,
594
609
event_id = room_for_user .event_id ,
595
610
event_pos = room_for_user .event_pos ,
596
611
membership = room_for_user .membership ,
@@ -691,6 +706,7 @@ async def get_sync_room_ids_for_user(
691
706
is not None
692
707
):
693
708
sync_room_id_set [room_id ] = _RoomMembershipForUser (
709
+ room_id = room_id ,
694
710
event_id = first_membership_change_after_to_token .prev_event_id ,
695
711
event_pos = first_membership_change_after_to_token .prev_event_pos ,
696
712
membership = first_membership_change_after_to_token .prev_membership ,
@@ -785,6 +801,7 @@ async def get_sync_room_ids_for_user(
785
801
# is their own leave event
786
802
if last_membership_change_in_from_to_range .membership == Membership .LEAVE :
787
803
filtered_sync_room_id_set [room_id ] = _RoomMembershipForUser (
804
+ room_id = room_id ,
788
805
event_id = last_membership_change_in_from_to_range .event_id ,
789
806
event_pos = last_membership_change_in_from_to_range .event_pos ,
790
807
membership = last_membership_change_in_from_to_range .membership ,
@@ -969,7 +986,7 @@ async def sort_rooms(
969
986
self ,
970
987
sync_room_map : Dict [str , _RoomMembershipForUser ],
971
988
to_token : StreamToken ,
972
- ) -> List [Tuple [ str , _RoomMembershipForUser ] ]:
989
+ ) -> List [_RoomMembershipForUser ]:
973
990
"""
974
991
Sort by `stream_ordering` of the last event that the user should see in the
975
992
room. `stream_ordering` is unique so we get a stable sort.
@@ -1007,12 +1024,17 @@ async def sort_rooms(
1007
1024
else :
1008
1025
# Otherwise, if the user has left/been invited/knocked/been banned from
1009
1026
# a room, they shouldn't see anything past that point.
1027
+ #
1028
+ # FIXME: It's possible that people should see beyond this point in
1029
+ # invited/knocked cases if for example the room has
1030
+ # `invite`/`world_readable` history visibility, see
1031
+ # https://github.com/matrix-org/matrix-spec-proposals/pull/3575#discussion_r1653045932
1010
1032
last_activity_in_room_map [room_id ] = room_for_user .event_pos .stream
1011
1033
1012
1034
return sorted (
1013
- sync_room_map .items (),
1035
+ sync_room_map .values (),
1014
1036
# Sort by the last activity (stream_ordering) in the room
1015
- key = lambda room_info : last_activity_in_room_map [room_info [ 0 ] ],
1037
+ key = lambda room_info : last_activity_in_room_map [room_info . room_id ],
1016
1038
# We want descending order
1017
1039
reverse = True ,
1018
1040
)
@@ -1022,7 +1044,7 @@ async def get_room_sync_data(
1022
1044
user : UserID ,
1023
1045
room_id : str ,
1024
1046
room_sync_config : RoomSyncConfig ,
1025
- rooms_membership_for_user_at_to_token : _RoomMembershipForUser ,
1047
+ room_membership_for_user_at_to_token : _RoomMembershipForUser ,
1026
1048
from_token : Optional [StreamToken ],
1027
1049
to_token : StreamToken ,
1028
1050
) -> SlidingSyncResult .RoomResult :
@@ -1036,7 +1058,7 @@ async def get_room_sync_data(
1036
1058
room_id: The room ID to fetch data for
1037
1059
room_sync_config: Config for what data we should fetch for a room in the
1038
1060
sync response.
1039
- rooms_membership_for_user_at_to_token : Membership information for the user
1061
+ room_membership_for_user_at_to_token : Membership information for the user
1040
1062
in the room at the time of `to_token`.
1041
1063
from_token: The point in the stream to sync from.
1042
1064
to_token: The point in the stream to sync up to.
@@ -1056,7 +1078,7 @@ async def get_room_sync_data(
1056
1078
if (
1057
1079
room_sync_config .timeline_limit > 0
1058
1080
# No timeline for invite/knock rooms (just `stripped_state`)
1059
- and rooms_membership_for_user_at_to_token .membership
1081
+ and room_membership_for_user_at_to_token .membership
1060
1082
not in (Membership .INVITE , Membership .KNOCK )
1061
1083
):
1062
1084
limited = False
@@ -1069,12 +1091,12 @@ async def get_room_sync_data(
1069
1091
# We're going to paginate backwards from the `to_token`
1070
1092
from_bound = to_token .room_key
1071
1093
# People shouldn't see past their leave/ban event
1072
- if rooms_membership_for_user_at_to_token .membership in (
1094
+ if room_membership_for_user_at_to_token .membership in (
1073
1095
Membership .LEAVE ,
1074
1096
Membership .BAN ,
1075
1097
):
1076
1098
from_bound = (
1077
- rooms_membership_for_user_at_to_token .event_pos .to_room_stream_token ()
1099
+ room_membership_for_user_at_to_token .event_pos .to_room_stream_token ()
1078
1100
)
1079
1101
1080
1102
# Determine whether we should limit the timeline to the token range.
@@ -1089,7 +1111,7 @@ async def get_room_sync_data(
1089
1111
to_bound = (
1090
1112
from_token .room_key
1091
1113
if from_token is not None
1092
- and not rooms_membership_for_user_at_to_token .newly_joined
1114
+ and not room_membership_for_user_at_to_token .newly_joined
1093
1115
else None
1094
1116
)
1095
1117
@@ -1126,7 +1148,7 @@ async def get_room_sync_data(
1126
1148
self .storage_controllers ,
1127
1149
user .to_string (),
1128
1150
timeline_events ,
1129
- is_peeking = rooms_membership_for_user_at_to_token .membership
1151
+ is_peeking = room_membership_for_user_at_to_token .membership
1130
1152
!= Membership .JOIN ,
1131
1153
filter_send_to_client = True ,
1132
1154
)
@@ -1181,16 +1203,16 @@ async def get_room_sync_data(
1181
1203
# Figure out any stripped state events for invite/knocks. This allows the
1182
1204
# potential joiner to identify the room.
1183
1205
stripped_state : List [JsonDict ] = []
1184
- if rooms_membership_for_user_at_to_token .membership in (
1206
+ if room_membership_for_user_at_to_token .membership in (
1185
1207
Membership .INVITE ,
1186
1208
Membership .KNOCK ,
1187
1209
):
1188
1210
# This should never happen. If someone is invited/knocked on room, then
1189
1211
# there should be an event for it.
1190
- assert rooms_membership_for_user_at_to_token .event_id is not None
1212
+ assert room_membership_for_user_at_to_token .event_id is not None
1191
1213
1192
1214
invite_or_knock_event = await self .store .get_event (
1193
- rooms_membership_for_user_at_to_token .event_id
1215
+ room_membership_for_user_at_to_token .event_id
1194
1216
)
1195
1217
1196
1218
stripped_state = []
@@ -1206,7 +1228,7 @@ async def get_room_sync_data(
1206
1228
stripped_state .append (strip_event (invite_or_knock_event ))
1207
1229
1208
1230
# TODO: Handle state resets. For example, if we see
1209
- # `rooms_membership_for_user_at_to_token .membership = Membership.LEAVE` but
1231
+ # `room_membership_for_user_at_to_token .membership = Membership.LEAVE` but
1210
1232
# `required_state` doesn't include it, we should indicate to the client that a
1211
1233
# state reset happened. Perhaps we should indicate this by setting `initial:
1212
1234
# True` and empty `required_state`.
@@ -1226,7 +1248,7 @@ async def get_room_sync_data(
1226
1248
# `invite`/`knock` rooms only have `stripped_state`. See
1227
1249
# https://github.com/matrix-org/matrix-spec-proposals/pull/3575#discussion_r1653045932
1228
1250
room_state : Optional [StateMap [EventBase ]] = None
1229
- if rooms_membership_for_user_at_to_token .membership not in (
1251
+ if room_membership_for_user_at_to_token .membership not in (
1230
1252
Membership .INVITE ,
1231
1253
Membership .KNOCK ,
1232
1254
):
@@ -1303,15 +1325,15 @@ async def get_room_sync_data(
1303
1325
# initial sync
1304
1326
if initial :
1305
1327
# People shouldn't see past their leave/ban event
1306
- if rooms_membership_for_user_at_to_token .membership in (
1328
+ if room_membership_for_user_at_to_token .membership in (
1307
1329
Membership .LEAVE ,
1308
1330
Membership .BAN ,
1309
1331
):
1310
1332
room_state = await self .storage_controllers .state .get_state_at (
1311
1333
room_id ,
1312
1334
stream_position = to_token .copy_and_replace (
1313
1335
StreamKeyType .ROOM ,
1314
- rooms_membership_for_user_at_to_token .event_pos .to_room_stream_token (),
1336
+ room_membership_for_user_at_to_token .event_pos .to_room_stream_token (),
1315
1337
),
1316
1338
state_filter = state_filter ,
1317
1339
# Partially-stated rooms should have all state events except for
@@ -1341,6 +1363,20 @@ async def get_room_sync_data(
1341
1363
# we can return updates instead of the full required state.
1342
1364
raise NotImplementedError ()
1343
1365
1366
+ # Figure out the last bump event in the room
1367
+ last_bump_event_result = (
1368
+ await self .store .get_last_event_pos_in_room_before_stream_ordering (
1369
+ room_id , to_token .room_key , event_types = DEFAULT_BUMP_EVENT_TYPES
1370
+ )
1371
+ )
1372
+
1373
+ # By default, just choose the membership event position
1374
+ bump_stamp = room_membership_for_user_at_to_token .event_pos .stream
1375
+ # But if we found a bump event, use that instead
1376
+ if last_bump_event_result is not None :
1377
+ _ , bump_event_pos = last_bump_event_result
1378
+ bump_stamp = bump_event_pos .stream
1379
+
1344
1380
return SlidingSyncResult .RoomResult (
1345
1381
# TODO: Dummy value
1346
1382
name = None ,
@@ -1358,6 +1394,7 @@ async def get_room_sync_data(
1358
1394
prev_batch = prev_batch_token ,
1359
1395
limited = limited ,
1360
1396
num_live = num_live ,
1397
+ bump_stamp = bump_stamp ,
1361
1398
# TODO: Dummy values
1362
1399
joined_count = 0 ,
1363
1400
invited_count = 0 ,
0 commit comments