Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Speed up remote invite rejection database call #8815

Merged
merged 6 commits into from
Nov 25, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/8815.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Optimise the lookup for an invite from another homeserver when trying to reject it.
17 changes: 12 additions & 5 deletions synapse/handlers/room_member.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
from synapse.api.ratelimiting import Ratelimiter
from synapse.events import EventBase
from synapse.events.snapshot import EventContext
from synapse.storage.roommember import RoomsForUser
from synapse.types import JsonDict, Requester, RoomAlias, RoomID, StateMap, UserID
from synapse.util.async_helpers import Linearizer
from synapse.util.distributor import user_left_room
Expand Down Expand Up @@ -515,10 +514,17 @@ async def update_membership_locked(
elif effective_membership_state == Membership.LEAVE:
if not is_host_in_room:
# perhaps we've been invited
invite = await self.store.get_invite_for_local_user_in_room(
user_id=target.to_string(), room_id=room_id
) # type: Optional[RoomsForUser]
if not invite:
(
current_membership_type,
current_membership_event_id,
) = await self.store.get_local_current_membership_for_user_in_room(
target.to_string(), room_id
)
if (
not current_membership_type
or current_membership_type != Membership.INVITE
anoadragon453 marked this conversation as resolved.
Show resolved Hide resolved
or not current_membership_event_id
):
logger.info(
"%s sent a leave request to %s, but that is not an active room "
"on this server, and there is no pending invite",
Expand All @@ -528,6 +534,7 @@ async def update_membership_locked(

raise SynapseError(404, "Not a known room")

invite = await self.store.get_event(current_membership_event_id)
logger.info(
"%s rejects invite to %s from %s", target, room_id, invite.sender
)
Expand Down
35 changes: 34 additions & 1 deletion synapse/storage/databases/main/roommember.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
from typing import TYPE_CHECKING, Dict, FrozenSet, Iterable, List, Optional, Set
from typing import TYPE_CHECKING, Dict, FrozenSet, Iterable, List, Optional, Set, Tuple

from synapse.api.constants import EventTypes, Membership
from synapse.events import EventBase
Expand Down Expand Up @@ -350,6 +350,39 @@ def _get_rooms_for_local_user_where_membership_is_txn(

return results

@cached()
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need to invalidate this cache ever?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yep! And after looking at the places this cache needs to be invalidated... it's a few.

It was a nice thought, but since this is quite a quick query I'm minded to not block a lot of work on a cache here :l

async def get_local_current_membership_for_user_in_room(
self, user_id: str, room_id: str
) -> Tuple[Optional[str], Optional[str]]:
"""Retrieve the current local membership state and event ID for a user in a room.

Args:
user_id: The ID of the user.
room_id: The ID of the room.

Returns:
A tuple of (membership_type, event_id). Both will be None if a
room_id/user_id pair is not found.
"""
# Paranoia check.
if not self.hs.is_mine_id(user_id):
raise Exception(
"Cannot call 'get_local_current_membership_for_user_in_room' on "
"non-local user %s" % (user_id,),
)

results_dict = await self.db_pool.simple_select_one(
"local_current_membership",
{"room_id": room_id, "user_id": user_id},
("membership", "event_id"),
allow_none=True,
desc="get_local_current_membership_for_user_in_room",
)
if not results_dict:
return None, None

return results_dict.get("membership"), results_dict.get("event_id")
clokep marked this conversation as resolved.
Show resolved Hide resolved

@cached(max_entries=500000, iterable=True)
async def get_rooms_for_user_with_stream_ordering(
self, user_id: str
Expand Down