@@ -1289,23 +1289,54 @@ async def _generate_sync_entry_for_device_list(
1289
1289
# room with by looking at all users that have left a room plus users
1290
1290
# that were in a room we've left.
1291
1291
1292
- users_who_share_room = await self .store .get_users_who_share_room_with_user (
1293
- user_id
1294
- )
1295
-
1296
- # Always tell the user about their own devices. We check as the user
1297
- # ID is almost certainly already included (unless they're not in any
1298
- # rooms) and taking a copy of the set is relatively expensive.
1299
- if user_id not in users_who_share_room :
1300
- users_who_share_room = set (users_who_share_room )
1301
- users_who_share_room .add (user_id )
1292
+ users_that_have_changed = set ()
1302
1293
1303
- tracked_users = users_who_share_room
1294
+ joined_rooms = sync_result_builder . joined_room_ids
1304
1295
1305
- # Step 1a, check for changes in devices of users we share a room with
1306
- users_that_have_changed = await self .store .get_users_whose_devices_changed (
1307
- since_token .device_list_key , tracked_users
1296
+ # Step 1a, check for changes in devices of users we share a room
1297
+ # with
1298
+ #
1299
+ # We do this in two different ways depending on what we have cached.
1300
+ # If we already have a list of all the user that have changed since
1301
+ # the last sync then it's likely more efficient to compare the rooms
1302
+ # they're in with the rooms the syncing user is in.
1303
+ #
1304
+ # If we don't have that info cached then we get all the users that
1305
+ # share a room with our user and check if those users have changed.
1306
+ changed_users = self .store .get_cached_device_list_changes (
1307
+ since_token .device_list_key
1308
1308
)
1309
+ if changed_users is not None :
1310
+ result = await self .store .get_rooms_for_users_with_stream_ordering (
1311
+ changed_users
1312
+ )
1313
+
1314
+ for changed_user_id , entries in result .items ():
1315
+ # Check if the changed user shares any rooms with the user,
1316
+ # or if the changed user is the syncing user (as we always
1317
+ # want to include device list updates of their own devices).
1318
+ if user_id == changed_user_id or any (
1319
+ e .room_id in joined_rooms for e in entries
1320
+ ):
1321
+ users_that_have_changed .add (changed_user_id )
1322
+ else :
1323
+ users_who_share_room = (
1324
+ await self .store .get_users_who_share_room_with_user (user_id )
1325
+ )
1326
+
1327
+ # Always tell the user about their own devices. We check as the user
1328
+ # ID is almost certainly already included (unless they're not in any
1329
+ # rooms) and taking a copy of the set is relatively expensive.
1330
+ if user_id not in users_who_share_room :
1331
+ users_who_share_room = set (users_who_share_room )
1332
+ users_who_share_room .add (user_id )
1333
+
1334
+ tracked_users = users_who_share_room
1335
+ users_that_have_changed = (
1336
+ await self .store .get_users_whose_devices_changed (
1337
+ since_token .device_list_key , tracked_users
1338
+ )
1339
+ )
1309
1340
1310
1341
# Step 1b, check for newly joined rooms
1311
1342
for room_id in newly_joined_rooms :
@@ -1329,7 +1360,14 @@ async def _generate_sync_entry_for_device_list(
1329
1360
newly_left_users .update (left_users )
1330
1361
1331
1362
# Remove any users that we still share a room with.
1332
- newly_left_users -= users_who_share_room
1363
+ left_users_rooms = (
1364
+ await self .store .get_rooms_for_users_with_stream_ordering (
1365
+ newly_left_users
1366
+ )
1367
+ )
1368
+ for user_id , entries in left_users_rooms .items ():
1369
+ if any (e .room_id in joined_rooms for e in entries ):
1370
+ newly_left_users .discard (user_id )
1333
1371
1334
1372
return DeviceLists (changed = users_that_have_changed , left = newly_left_users )
1335
1373
else :
0 commit comments