Skip to content

Reorder rooms by read receipts to update most important rooms first#19613

Open
neilisfragile wants to merge 8 commits into
developfrom
neilj/improve_perceived_display_name_performance
Open

Reorder rooms by read receipts to update most important rooms first#19613
neilisfragile wants to merge 8 commits into
developfrom
neilj/improve_perceived_display_name_performance

Conversation

@neilisfragile
Copy link
Copy Markdown
Member

@neilisfragile neilisfragile commented Mar 27, 2026

Problem to solve

Updating profile information, such as display name or avatar, requires updating state events in every room the user is part of. For large accounts, this can be a time-consuming operation. Historically, making an update led to a timeout and an ugly/confusing error to the user.

#17074 tried to fix this problem by returning immediately and then running the updates asynchronously in the background. The PR stalled due to time constraints, and the same problem was addressed and merged in #19311

#19311 fixed the timeout issue, but for large accounts, the experience is still jarring because rooms do not update immediately, so from the user's perspective, the update appears to have failed.

One aspect of #17074 that did not make it to #19311 is to order the room update by likely importance to the user.

This PR tries to address the importance issue by ordering the room list by read receipt rather than alphabetically. Since we're now processing rooms in the order of last read receipt, it will appear to be better because the rooms that the user looks at will be updated and hide the fact that we're still working on things in the background.

The important consideration is that once the room ordering is determined, it is never updated, even over a restart. This ensures all rooms are updated eventually.

Long term we might try to fix this with https://github.com/matrix-org/matrix-spec-proposals/blob/kegan/profile-changes/proposals/4218-profile-change-perf.md

Note, I had a first attempt to fix this in #19311, which, in retrospect, was overly complicated and tried to maintain two orderings (stream ordering and alphabetical).

Many thanks to @MatMaul for #19311

Pull Request Checklist

  • Pull request is based on the develop branch
  • Pull request includes a changelog file. The entry should:
    • Be a short description of your change which makes sense to users. "Fixed a bug that prevented receiving messages from other servers." instead of "Moved X method from EventStore to EventWorkerStore.".
    • Use markdown where necessary, mostly for code blocks.
    • End with either a period (.) or an exclamation mark (!).
    • Start with a capital letter.
    • Feel free to credit yourself, by adding a sentence "Contributed by @github_username." or "Contributed by [Your Name]." to the end of the entry.
  • Code style is correct (run the linters)

This PR is Claude-assisted, though line by line, I am confident in its operation.

@neilisfragile neilisfragile requested a review from a team as a code owner March 27, 2026 09:49
@neilisfragile neilisfragile marked this pull request as draft March 27, 2026 10:21
@neilisfragile neilisfragile marked this pull request as ready for review March 27, 2026 11:06
Comment thread changelog.d/19613.feature
Comment thread changelog.d/19613.feature
Comment thread synapse/handlers/profile.py Outdated
Comment on lines +727 to +745
all_room_ids = await self.store.get_rooms_for_user(target_user.to_string())

# Get the user's latest read receipts for all rooms
user_receipts = await self.store.get_receipts_for_user_with_orderings(
target_user.to_string(),
[ReceiptTypes.READ, ReceiptTypes.READ_PRIVATE],
)

# Sort rooms by most recent read receipt (highest stream_ordering first),
# with fallback to alphabetical ordering for rooms without receipts
def sort_key(room_id: str) -> tuple[int, str]:
if room_id in user_receipts:
# Rooms with receipts: sort by stream_ordering (descending) then by room_id
return (-user_receipts[room_id]["stream_ordering"], room_id)
else:
# Rooms without receipts: sort alphabetically after all rooms with receipts
return (0, room_id)

room_ids = sorted(all_room_ids, key=sort_key)
Copy link
Copy Markdown
Contributor

@MatMaul MatMaul Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The important consideration is that once the room ordering is determined, it is never updated, even over a restart. This ensures all rooms are updated eventually.

I don't think this is true?
From what I can see the list will be computed again on the next call to the task after a restart for example, and we hence may miss rooms if they were read in the meantime.

I think you should:

  • pre compute the ordered list of room ids in _update_join_states before scheduling the task
  • schedule the task with the list stored in task.params
  • add a test for that :) test_background_update_room_membership_resume_after_restart is simulating a restart so you should probably take that as an example
  • put less trust in Claude output

@MadLittleMods MadLittleMods removed the request for review from a team April 10, 2026 21:50
Comment thread changelog.d/19613.feature
@@ -0,0 +1 @@
Reorder rooms by read receipts to update most important rooms first.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing from the review queue until #19613 (comment) gets some attention ⏩

@neilisfragile
Copy link
Copy Markdown
Member Author

The PR is consistently failing on the worker version of the complement test TestThreadedReceipts

It is unclear why the changes are causing the failure, but even though it is on the flaky tests list, I think there is something to dig into.

@MadLittleMods
Copy link
Copy Markdown
Contributor

(for reference, the tests passed on the last run)

@neilisfragile
Copy link
Copy Markdown
Member Author

(for reference, the tests passed on the last run)

Yes, and I can't yet reproduce it locally either. There are still one or two things I want to try before just blaming a flaky test.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants