From daa8d7a28dc05bb0105c688be7fb96e2c06c950f Mon Sep 17 00:00:00 2001 From: Jason Robinson Date: Tue, 23 Jun 2026 12:39:07 +0300 Subject: [PATCH] Ensure lazy loaded profile updates in sync contain full profiles for users in timeline --- synapse/handlers/sync.py | 17 +++++++++++++---- tests/handlers/test_sync.py | 23 +++++++++++++++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/synapse/handlers/sync.py b/synapse/handlers/sync.py index 19c63945c8..f36a36b3d5 100644 --- a/synapse/handlers/sync.py +++ b/synapse/handlers/sync.py @@ -2316,10 +2316,19 @@ class SyncHandler: continue per_user_updates: dict[str, JsonValue] = {} - for field_name in fields: - per_user_updates[field_name] = cast( - JsonValue, profile_data.get(field_name) - ) + if include_users and other_user_id in include_users: + # Include the full profile as this user has events in + # a lazy loaded sync response + for field_name in profile_data.keys(): + per_user_updates[field_name] = cast( + JsonValue, profile_data.get(field_name) + ) + else: + # Include only the diff + for field_name in fields: + per_user_updates[field_name] = cast( + JsonValue, profile_data.get(field_name) + ) if per_user_updates: profile_updates[other_user_id] = per_user_updates diff --git a/tests/handlers/test_sync.py b/tests/handlers/test_sync.py index fdc9cb4726..2c5fd21599 100644 --- a/tests/handlers/test_sync.py +++ b/tests/handlers/test_sync.py @@ -1383,6 +1383,10 @@ class SyncProfileUpdatesTestCase(tests.unittest.HomeserverTestCase): incremental_result.profile_updates["@other_user:test"]["m.status"], '{"text": "On holiday", "emoji": "\\ud83c\\udfd6"}', ) + # We only send diffs in incremental sync for profile field updates + self.assertIsNone( + incremental_result.profile_updates["@other_user:test"].get("displayname"), + ) @override_config({"experimental_features": {"msc4429_enabled": True}}) def test_incremental_sync_does_not_filter_profile_updates_when_lazy_loading( @@ -1468,6 +1472,25 @@ class SyncProfileUpdatesTestCase(tests.unittest.HomeserverTestCase): "@third_user:test", ], ) + # This is a field upfate, so should be here + self.assertEqual( + incremental_result.profile_updates["@other_user:test"]["m.status"], + '{"text": "On holiday", "emoji": "\\ud83c\\udfd6"}', + ) + # We don't have events for this user in this response, so their full profile + # is not included + self.assertIsNone( + incremental_result.profile_updates["@other_user:test"].get("displayname"), + ) + # This user has events in the timeline, thus their full profile is included + self.assertEqual( + incremental_result.profile_updates["@third_user:test"]["m.status"], + '{"text": "On fire", "emoji": "\\ud83d\\udd25"}', + ) + self.assertEqual( + incremental_result.profile_updates["@third_user:test"]["displayname"], + "third_user", + ) class SyncStateAfterTestCase(tests.unittest.HomeserverTestCase):