Ensure both initial and incremental syncs include our own profile and updates

Otherwise if the user has multiple clients doing incremental sync, they wont get their own profile updates to their other clients. For initial because it should probably match the incremental behaviour + it avoids clients needing to look up the profile separately potentially.
This commit is contained in:
Jason Robinson
2026-07-01 11:22:57 +03:00
parent a460c285a7
commit eb5aa2129a
6 changed files with 82 additions and 15 deletions
+4 -7
View File
@@ -142,13 +142,10 @@ class ProfileHandler:
user_id.to_string()
)
)
# Remove ourselves from the user ID list
users_who_share_rooms.remove(user_id.to_string())
if users_who_share_rooms:
await self.store.track_profile_updates_per_user(
stream_id=stream_id,
user_ids=users_who_share_rooms,
)
await self.store.track_profile_updates_per_user(
stream_id=stream_id,
user_ids=users_who_share_rooms,
)
self._notifier.on_new_event(
StreamKeyType.PROFILE_UPDATES, stream_id, rooms=room_ids
-5
View File
@@ -2203,11 +2203,6 @@ class SyncHandler:
# Filter down to selected included users
user_ids = {user_id for user_id in user_ids if user_id in include_users}
# Remove ourselves
# FIXME?: Should `get_local_users_who_share_room_with_user` even return
# ourselves?
user_ids.discard(user_id)
if not user_ids:
return
+1 -1
View File
@@ -670,7 +670,7 @@ class ProfileWorkerStore(SQLBaseStore):
) -> None:
"""
Create tracking rows for profile updater per target user interested in profile
updates for the user triggering one.
updates for the user triggering one, including themselves.
Args:
stream_id: Stream ID referencing a `profile_updates` stream ID.
+4 -1
View File
@@ -983,7 +983,10 @@ class RoomMemberWorkerStore(EventsWorkerStore, CacheInvalidationWorkerStore):
return user_who_share_room
async def get_local_users_who_share_room_with_user(self, user_id: str) -> set[str]:
"""Returns the set of local users who share a room with `user_id`"""
"""Returns the set of local users who share a room with `user_id`.
This also includes the `user_id` themselves.
"""
room_ids = await self.get_rooms_for_user(user_id)
user_who_share_room: set[str] = set()
+6
View File
@@ -415,6 +415,12 @@ class ProfileTestCase(unittest.HomeserverTestCase):
action="joined_room",
field_name=None,
),
ProfileUpdate(
stream_id=4,
user_id=self.frank.to_string(),
action="update",
field_name="m.status",
),
],
)
+67 -1
View File
@@ -1241,7 +1241,8 @@ class SyncProfileUpdatesTestCase(tests.unittest.HomeserverTestCase):
@override_config({"include_profile_updates_in_sync": True})
def test_initial_sync_responds_with_tracked_profile_updates(self) -> None:
"""Test that with MSC4429 enabled the initial sync response does
contain profile updates for users who share rooms."""
contain profile updates for users who share rooms, including our
syncing user."""
self.get_success(
self.profile_handler.set_field(
target_user=UserID.from_string(self.other_user),
@@ -1269,6 +1270,7 @@ class SyncProfileUpdatesTestCase(tests.unittest.HomeserverTestCase):
request_key=generate_request_key(),
)
)
assert initial_result.profile_updates[self.user] is not None
assert initial_result.profile_updates["@other_user:test"] is not None
self.assertEqual(
initial_result.profile_updates["@other_user:test"]["m.status"],
@@ -1277,6 +1279,7 @@ class SyncProfileUpdatesTestCase(tests.unittest.HomeserverTestCase):
self.assertCountEqual(
initial_result.profile_updates.keys(),
[
self.user,
"@other_user:test",
],
)
@@ -1804,6 +1807,69 @@ class SyncProfileUpdatesTestCase(tests.unittest.HomeserverTestCase):
incremental_result.profile_updates["@third_user:test"]["avatar_url"],
)
@parameterized.expand(
[
True,
False,
]
)
@override_config({"include_profile_updates_in_sync": True})
def test_incremental_sync_includes_own_profile_updates(self, is_lazy: bool) -> None:
"""Test that with MSC4429 enabled the incremental sync response includes
ones own profile updates."""
requester = create_requester(self.user)
filter_json: dict[str, dict] = {
"org.matrix.msc4429.profile_fields": {
"ids": ["m.status", "displayname", "avatar_url"]
}
}
if is_lazy:
filter_json["room"] = {
"state": {
"lazy_load_members": True,
},
}
initial_result = self.get_success(
self.sync_handler.wait_for_sync_for_user(
requester,
sync_config=generate_sync_config(
user_id=self.user,
filter_collection=FilterCollection(
hs=self.hs,
filter_json=filter_json,
),
),
request_key=generate_request_key(),
)
)
self.get_success(
self.profile_handler.set_field(
target_user=UserID.from_string(self.user),
requester=requester,
field_name="m.status",
new_value=json.dumps({"text": "On holiday", "emoji": "🏖"}),
)
)
incremental_result = self.get_success(
self.sync_handler.wait_for_sync_for_user(
requester,
since_token=initial_result.next_batch,
sync_config=generate_sync_config(
user_id=self.user,
filter_collection=FilterCollection(
hs=self.hs,
filter_json=filter_json,
),
),
request_key=generate_request_key(),
)
)
assert incremental_result.profile_updates["@user:test"] is not None
self.assertEqual(
incremental_result.profile_updates["@user:test"]["m.status"],
'{"text": "On holiday", "emoji": "\\ud83c\\udfd6"}',
)
class SyncStateAfterTestCase(tests.unittest.HomeserverTestCase):
"""Tests Sync Handler state behavior when using `use_state_after."""