Read a joining local user's profile in one query

A join without profile data read the user's display name and then their
avatar URL, two transactions. For a local user with neither in the
content, `get_profileinfo` now reads both at once. A remote user, or
content that has one of the two, takes the same path as before.

If the user has no profile row, the first read used to fail with a 404,
logged, and leave both out. Now both are left out without the log line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PVLsNh6akt4ifEizY4D1ta
This commit is contained in:
Erik JohnstonandClaude Opus 5.5 committed 2026-10-18 21:34:52 +00:00
1 parent 7eac9c44b6
commit 43d2a88e30
2 files changed
+38 -8

No files matched your search

+20 -8
View File
@@ -823,14 +823,26 @@ class RoomMemberHandler(metaclass=abc.ABCMeta):
profile = self.profile_handler
try:
if "displayname" not in content:
displayname = await profile.get_displayname(target)
if displayname is not None:
content["displayname"] = displayname
if "avatar_url" not in content:
avatar_url = await profile.get_avatar_url(target)
if avatar_url is not None:
content["avatar_url"] = avatar_url
if (
"displayname" not in content
and "avatar_url" not in content
and self.hs.is_mine(target)
):
# Both in one query.
info = await self.store.get_profileinfo(target)
if info.display_name is not None:
content["displayname"] = info.display_name
if info.avatar_url is not None:
content["avatar_url"] = info.avatar_url
else:
if "displayname" not in content:
displayname = await profile.get_displayname(target)
if displayname is not None:
content["displayname"] = displayname
if "avatar_url" not in content:
avatar_url = await profile.get_avatar_url(target)
if avatar_url is not None:
content["avatar_url"] = avatar_url
except Exception as e:
logger.info("Failed to get profile information for %r: %s", target, e)
+18
View File
@@ -3446,6 +3446,24 @@ class PerRoomProfilesForbiddenTestCase(unittest.HomeserverTestCase):
self.room_id = self.helper.create_room_as(self.user_id, tok=self.tok)
def test_join_has_the_global_profile(self) -> None:
"""A join without profile data gets the user's display name and
avatar."""
channel = self.make_request(
"PUT",
"/_matrix/client/r0/profile/%s/avatar_url" % (self.user_id,),
{"avatar_url": "mxc://test/avatar"},
access_token=self.tok,
)
self.assertEqual(channel.code, HTTPStatus.OK, channel.result)
room_id = self.helper.create_room_as(self.user_id, tok=self.tok)
member = self.helper.get_state(
room_id, "m.room.member", self.tok, state_key=self.user_id
)
self.assertEqual(member["displayname"], self.displayname)
self.assertEqual(member["avatar_url"], "mxc://test/avatar")
def test_per_room_profile_forbidden(self) -> None:
request_data = {"membership": "join", "displayname": "other test user"}
channel = self.make_request(