Speed up sliding sync by avoiding copies (#17670)
We ended up spending ~10% CPU creating a new dictionary and `_RoomMembershipForUser`, so let's avoid creating new dicts and copying by returning `newly_joined`, `newly_left` and `is_dm` as sets directly. --------- Co-authored-by: Eric Eastwood <eric.eastwood@beta.gouv.fr>
This commit is contained in:
parent
de3363ef58
commit
d5accec2e5
|
@ -0,0 +1 @@
|
||||||
|
Small performance improvement in speeding up sliding sync.
|
|
@ -25,8 +25,8 @@ from synapse.events.utils import strip_event
|
||||||
from synapse.handlers.relations import BundledAggregations
|
from synapse.handlers.relations import BundledAggregations
|
||||||
from synapse.handlers.sliding_sync.extensions import SlidingSyncExtensionHandler
|
from synapse.handlers.sliding_sync.extensions import SlidingSyncExtensionHandler
|
||||||
from synapse.handlers.sliding_sync.room_lists import (
|
from synapse.handlers.sliding_sync.room_lists import (
|
||||||
|
RoomsForUserType,
|
||||||
SlidingSyncRoomLists,
|
SlidingSyncRoomLists,
|
||||||
_RoomMembershipForUser,
|
|
||||||
)
|
)
|
||||||
from synapse.handlers.sliding_sync.store import SlidingSyncConnectionStore
|
from synapse.handlers.sliding_sync.store import SlidingSyncConnectionStore
|
||||||
from synapse.logging.opentracing import (
|
from synapse.logging.opentracing import (
|
||||||
|
@ -39,7 +39,9 @@ from synapse.logging.opentracing import (
|
||||||
)
|
)
|
||||||
from synapse.storage.databases.main.roommember import extract_heroes_from_room_summary
|
from synapse.storage.databases.main.roommember import extract_heroes_from_room_summary
|
||||||
from synapse.storage.databases.main.stream import PaginateFunction
|
from synapse.storage.databases.main.stream import PaginateFunction
|
||||||
from synapse.storage.roommember import MemberSummary
|
from synapse.storage.roommember import (
|
||||||
|
MemberSummary,
|
||||||
|
)
|
||||||
from synapse.types import (
|
from synapse.types import (
|
||||||
JsonDict,
|
JsonDict,
|
||||||
PersistedEventPosition,
|
PersistedEventPosition,
|
||||||
|
@ -255,6 +257,8 @@ class SlidingSyncHandler:
|
||||||
],
|
],
|
||||||
from_token=from_token,
|
from_token=from_token,
|
||||||
to_token=to_token,
|
to_token=to_token,
|
||||||
|
newly_joined=room_id in interested_rooms.newly_joined_rooms,
|
||||||
|
is_dm=room_id in interested_rooms.dm_room_ids,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Filter out empty room results during incremental sync
|
# Filter out empty room results during incremental sync
|
||||||
|
@ -352,7 +356,7 @@ class SlidingSyncHandler:
|
||||||
async def get_current_state_ids_at(
|
async def get_current_state_ids_at(
|
||||||
self,
|
self,
|
||||||
room_id: str,
|
room_id: str,
|
||||||
room_membership_for_user_at_to_token: _RoomMembershipForUser,
|
room_membership_for_user_at_to_token: RoomsForUserType,
|
||||||
state_filter: StateFilter,
|
state_filter: StateFilter,
|
||||||
to_token: StreamToken,
|
to_token: StreamToken,
|
||||||
) -> StateMap[str]:
|
) -> StateMap[str]:
|
||||||
|
@ -417,7 +421,7 @@ class SlidingSyncHandler:
|
||||||
async def get_current_state_at(
|
async def get_current_state_at(
|
||||||
self,
|
self,
|
||||||
room_id: str,
|
room_id: str,
|
||||||
room_membership_for_user_at_to_token: _RoomMembershipForUser,
|
room_membership_for_user_at_to_token: RoomsForUserType,
|
||||||
state_filter: StateFilter,
|
state_filter: StateFilter,
|
||||||
to_token: StreamToken,
|
to_token: StreamToken,
|
||||||
) -> StateMap[EventBase]:
|
) -> StateMap[EventBase]:
|
||||||
|
@ -457,9 +461,11 @@ class SlidingSyncHandler:
|
||||||
new_connection_state: "MutablePerConnectionState",
|
new_connection_state: "MutablePerConnectionState",
|
||||||
room_id: str,
|
room_id: str,
|
||||||
room_sync_config: RoomSyncConfig,
|
room_sync_config: RoomSyncConfig,
|
||||||
room_membership_for_user_at_to_token: _RoomMembershipForUser,
|
room_membership_for_user_at_to_token: RoomsForUserType,
|
||||||
from_token: Optional[SlidingSyncStreamToken],
|
from_token: Optional[SlidingSyncStreamToken],
|
||||||
to_token: StreamToken,
|
to_token: StreamToken,
|
||||||
|
newly_joined: bool,
|
||||||
|
is_dm: bool,
|
||||||
) -> SlidingSyncResult.RoomResult:
|
) -> SlidingSyncResult.RoomResult:
|
||||||
"""
|
"""
|
||||||
Fetch room data for the sync response.
|
Fetch room data for the sync response.
|
||||||
|
@ -475,6 +481,8 @@ class SlidingSyncHandler:
|
||||||
in the room at the time of `to_token`.
|
in the room at the time of `to_token`.
|
||||||
from_token: The point in the stream to sync from.
|
from_token: The point in the stream to sync from.
|
||||||
to_token: The point in the stream to sync up to.
|
to_token: The point in the stream to sync up to.
|
||||||
|
newly_joined: If the user has newly joined the room
|
||||||
|
is_dm: Whether the room is a DM room
|
||||||
"""
|
"""
|
||||||
user = sync_config.user
|
user = sync_config.user
|
||||||
|
|
||||||
|
@ -519,7 +527,7 @@ class SlidingSyncHandler:
|
||||||
from_bound = None
|
from_bound = None
|
||||||
initial = True
|
initial = True
|
||||||
ignore_timeline_bound = False
|
ignore_timeline_bound = False
|
||||||
if from_token and not room_membership_for_user_at_to_token.newly_joined:
|
if from_token and not newly_joined:
|
||||||
room_status = previous_connection_state.rooms.have_sent_room(room_id)
|
room_status = previous_connection_state.rooms.have_sent_room(room_id)
|
||||||
if room_status.status == HaveSentRoomFlag.LIVE:
|
if room_status.status == HaveSentRoomFlag.LIVE:
|
||||||
from_bound = from_token.stream_token.room_key
|
from_bound = from_token.stream_token.room_key
|
||||||
|
@ -1044,7 +1052,7 @@ class SlidingSyncHandler:
|
||||||
name=room_name,
|
name=room_name,
|
||||||
avatar=room_avatar,
|
avatar=room_avatar,
|
||||||
heroes=heroes,
|
heroes=heroes,
|
||||||
is_dm=room_membership_for_user_at_to_token.is_dm,
|
is_dm=is_dm,
|
||||||
initial=initial,
|
initial=initial,
|
||||||
required_state=list(required_room_state.values()),
|
required_state=list(required_room_state.values()),
|
||||||
timeline_events=timeline_events,
|
timeline_events=timeline_events,
|
||||||
|
|
|
@ -19,7 +19,6 @@ from itertools import chain
|
||||||
from typing import (
|
from typing import (
|
||||||
TYPE_CHECKING,
|
TYPE_CHECKING,
|
||||||
AbstractSet,
|
AbstractSet,
|
||||||
Any,
|
|
||||||
Dict,
|
Dict,
|
||||||
List,
|
List,
|
||||||
Literal,
|
Literal,
|
||||||
|
@ -48,7 +47,11 @@ from synapse.storage.databases.main.state import (
|
||||||
Sentinel as StateSentinel,
|
Sentinel as StateSentinel,
|
||||||
)
|
)
|
||||||
from synapse.storage.databases.main.stream import CurrentStateDeltaMembership
|
from synapse.storage.databases.main.stream import CurrentStateDeltaMembership
|
||||||
from synapse.storage.roommember import RoomsForUser, RoomsForUserSlidingSync
|
from synapse.storage.roommember import (
|
||||||
|
RoomsForUser,
|
||||||
|
RoomsForUserSlidingSync,
|
||||||
|
RoomsForUserStateReset,
|
||||||
|
)
|
||||||
from synapse.types import (
|
from synapse.types import (
|
||||||
MutableStateMap,
|
MutableStateMap,
|
||||||
PersistedEventPosition,
|
PersistedEventPosition,
|
||||||
|
@ -76,6 +79,11 @@ if TYPE_CHECKING:
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
# Helper definition for the types that we might return. We do this to avoid
|
||||||
|
# copying data between types (which can be expensive for many rooms).
|
||||||
|
RoomsForUserType = Union[RoomsForUserStateReset, RoomsForUser, RoomsForUserSlidingSync]
|
||||||
|
|
||||||
|
|
||||||
@attr.s(auto_attribs=True, slots=True, frozen=True)
|
@attr.s(auto_attribs=True, slots=True, frozen=True)
|
||||||
class SlidingSyncInterestedRooms:
|
class SlidingSyncInterestedRooms:
|
||||||
"""The set of rooms and metadata a client is interested in based on their
|
"""The set of rooms and metadata a client is interested in based on their
|
||||||
|
@ -91,13 +99,22 @@ class SlidingSyncInterestedRooms:
|
||||||
includes the rooms that *may* have relevant updates. Rooms not
|
includes the rooms that *may* have relevant updates. Rooms not
|
||||||
in this map will definitely not have room updates (though
|
in this map will definitely not have room updates (though
|
||||||
extensions may have updates in these rooms).
|
extensions may have updates in these rooms).
|
||||||
|
newly_joined_rooms: The set of rooms that were joined in the token range
|
||||||
|
and the user is still joined to at the end of this range.
|
||||||
|
newly_left_rooms: The set of rooms that we left in the token range
|
||||||
|
and are still "leave" at the end of this range.
|
||||||
|
dm_room_ids: The set of rooms the user consider as direct-message (DM) rooms
|
||||||
"""
|
"""
|
||||||
|
|
||||||
lists: Mapping[str, SlidingSyncResult.SlidingWindowList]
|
lists: Mapping[str, SlidingSyncResult.SlidingWindowList]
|
||||||
relevant_room_map: Mapping[str, RoomSyncConfig]
|
relevant_room_map: Mapping[str, RoomSyncConfig]
|
||||||
relevant_rooms_to_send_map: Mapping[str, RoomSyncConfig]
|
relevant_rooms_to_send_map: Mapping[str, RoomSyncConfig]
|
||||||
all_rooms: Set[str]
|
all_rooms: Set[str]
|
||||||
room_membership_for_user_map: Mapping[str, "_RoomMembershipForUser"]
|
room_membership_for_user_map: Mapping[str, RoomsForUserType]
|
||||||
|
|
||||||
|
newly_joined_rooms: AbstractSet[str]
|
||||||
|
newly_left_rooms: AbstractSet[str]
|
||||||
|
dm_room_ids: AbstractSet[str]
|
||||||
|
|
||||||
|
|
||||||
class Sentinel(enum.Enum):
|
class Sentinel(enum.Enum):
|
||||||
|
@ -106,47 +123,10 @@ class Sentinel(enum.Enum):
|
||||||
UNSET_SENTINEL = object()
|
UNSET_SENTINEL = object()
|
||||||
|
|
||||||
|
|
||||||
@attr.s(slots=True, frozen=True, auto_attribs=True)
|
|
||||||
class _RoomMembershipForUser:
|
|
||||||
"""
|
|
||||||
Attributes:
|
|
||||||
room_id: The room ID of the membership event
|
|
||||||
event_id: The event ID of the membership event
|
|
||||||
event_pos: The stream position of the membership event
|
|
||||||
membership: The membership state of the user in the room
|
|
||||||
sender: The person who sent the membership event
|
|
||||||
newly_joined: Whether the user newly joined the room during the given token
|
|
||||||
range and is still joined to the room at the end of this range.
|
|
||||||
newly_left: Whether the user newly left (or kicked) the room during the given
|
|
||||||
token range and is still "leave" at the end of this range.
|
|
||||||
is_dm: Whether this user considers this room as a direct-message (DM) room
|
|
||||||
"""
|
|
||||||
|
|
||||||
room_id: str
|
|
||||||
# Optional because state resets can affect room membership without a corresponding event.
|
|
||||||
event_id: Optional[str]
|
|
||||||
# Even during a state reset which removes the user from the room, we expect this to
|
|
||||||
# be set because `current_state_delta_stream` will note the position that the reset
|
|
||||||
# happened.
|
|
||||||
event_pos: PersistedEventPosition
|
|
||||||
# Even during a state reset which removes the user from the room, we expect this to
|
|
||||||
# be set to `LEAVE` because we can make that assumption based on the situaton (see
|
|
||||||
# `get_current_state_delta_membership_changes_for_user(...)`)
|
|
||||||
membership: str
|
|
||||||
# Optional because state resets can affect room membership without a corresponding event.
|
|
||||||
sender: Optional[str]
|
|
||||||
newly_joined: bool
|
|
||||||
newly_left: bool
|
|
||||||
is_dm: bool
|
|
||||||
|
|
||||||
def copy_and_replace(self, **kwds: Any) -> "_RoomMembershipForUser":
|
|
||||||
return attr.evolve(self, **kwds)
|
|
||||||
|
|
||||||
|
|
||||||
def filter_membership_for_sync(
|
def filter_membership_for_sync(
|
||||||
*,
|
*,
|
||||||
user_id: str,
|
user_id: str,
|
||||||
room_membership_for_user: Union[_RoomMembershipForUser, RoomsForUserSlidingSync],
|
room_membership_for_user: RoomsForUserType,
|
||||||
newly_left: bool,
|
newly_left: bool,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
|
@ -479,22 +459,10 @@ class SlidingSyncRoomLists:
|
||||||
relevant_room_map=relevant_room_map,
|
relevant_room_map=relevant_room_map,
|
||||||
relevant_rooms_to_send_map=relevant_rooms_to_send_map,
|
relevant_rooms_to_send_map=relevant_rooms_to_send_map,
|
||||||
all_rooms=all_rooms,
|
all_rooms=all_rooms,
|
||||||
room_membership_for_user_map={
|
room_membership_for_user_map=room_membership_for_user_map,
|
||||||
# FIXME: Ideally we wouldn't have to create a new
|
newly_joined_rooms=newly_joined_room_ids,
|
||||||
# `_RoomMembershipForUser` here and instead just return
|
newly_left_rooms=set(newly_left_room_map),
|
||||||
# `newly_joined_room_ids` directly, to save CPU time.
|
dm_room_ids=dm_room_ids,
|
||||||
room_id: _RoomMembershipForUser(
|
|
||||||
room_id=room_id,
|
|
||||||
event_id=membership_info.event_id,
|
|
||||||
event_pos=membership_info.event_pos,
|
|
||||||
sender=membership_info.sender,
|
|
||||||
membership=membership_info.membership,
|
|
||||||
newly_joined=room_id in newly_joined_room_ids,
|
|
||||||
newly_left=room_id in newly_left_room_map,
|
|
||||||
is_dm=room_id in dm_room_ids,
|
|
||||||
)
|
|
||||||
for room_id, membership_info in room_membership_for_user_map.items()
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
async def _compute_interested_rooms_fallback(
|
async def _compute_interested_rooms_fallback(
|
||||||
|
@ -506,12 +474,16 @@ class SlidingSyncRoomLists:
|
||||||
) -> SlidingSyncInterestedRooms:
|
) -> SlidingSyncInterestedRooms:
|
||||||
"""Fallback code when the database background updates haven't completed yet."""
|
"""Fallback code when the database background updates haven't completed yet."""
|
||||||
|
|
||||||
room_membership_for_user_map = (
|
(
|
||||||
await self.get_room_membership_for_user_at_to_token(
|
room_membership_for_user_map,
|
||||||
sync_config.user, to_token, from_token
|
newly_joined_room_ids,
|
||||||
)
|
newly_left_room_ids,
|
||||||
|
) = await self.get_room_membership_for_user_at_to_token(
|
||||||
|
sync_config.user, to_token, from_token
|
||||||
)
|
)
|
||||||
|
|
||||||
|
dm_room_ids = await self._get_dm_rooms_for_user(sync_config.user.to_string())
|
||||||
|
|
||||||
# Assemble sliding window lists
|
# Assemble sliding window lists
|
||||||
lists: Dict[str, SlidingSyncResult.SlidingWindowList] = {}
|
lists: Dict[str, SlidingSyncResult.SlidingWindowList] = {}
|
||||||
# Keep track of the rooms that we can display and need to fetch more info about
|
# Keep track of the rooms that we can display and need to fetch more info about
|
||||||
|
@ -525,6 +497,7 @@ class SlidingSyncRoomLists:
|
||||||
sync_room_map = await self.filter_rooms_relevant_for_sync(
|
sync_room_map = await self.filter_rooms_relevant_for_sync(
|
||||||
user=sync_config.user,
|
user=sync_config.user,
|
||||||
room_membership_for_user_map=room_membership_for_user_map,
|
room_membership_for_user_map=room_membership_for_user_map,
|
||||||
|
newly_left_room_ids=newly_left_room_ids,
|
||||||
)
|
)
|
||||||
|
|
||||||
for list_key, list_config in sync_config.lists.items():
|
for list_key, list_config in sync_config.lists.items():
|
||||||
|
@ -536,6 +509,7 @@ class SlidingSyncRoomLists:
|
||||||
sync_room_map,
|
sync_room_map,
|
||||||
list_config.filters,
|
list_config.filters,
|
||||||
to_token,
|
to_token,
|
||||||
|
dm_room_ids,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Find which rooms are partially stated and may need to be filtered out
|
# Find which rooms are partially stated and may need to be filtered out
|
||||||
|
@ -679,6 +653,9 @@ class SlidingSyncRoomLists:
|
||||||
relevant_rooms_to_send_map=relevant_rooms_to_send_map,
|
relevant_rooms_to_send_map=relevant_rooms_to_send_map,
|
||||||
all_rooms=all_rooms,
|
all_rooms=all_rooms,
|
||||||
room_membership_for_user_map=room_membership_for_user_map,
|
room_membership_for_user_map=room_membership_for_user_map,
|
||||||
|
newly_joined_rooms=newly_joined_room_ids,
|
||||||
|
newly_left_rooms=newly_left_room_ids,
|
||||||
|
dm_room_ids=dm_room_ids,
|
||||||
)
|
)
|
||||||
|
|
||||||
async def _filter_relevant_room_to_send(
|
async def _filter_relevant_room_to_send(
|
||||||
|
@ -755,7 +732,7 @@ class SlidingSyncRoomLists:
|
||||||
async def _get_rewind_changes_to_current_membership_to_token(
|
async def _get_rewind_changes_to_current_membership_to_token(
|
||||||
self,
|
self,
|
||||||
user: UserID,
|
user: UserID,
|
||||||
rooms_for_user: Mapping[str, Union[RoomsForUser, RoomsForUserSlidingSync]],
|
rooms_for_user: Mapping[str, RoomsForUserType],
|
||||||
to_token: StreamToken,
|
to_token: StreamToken,
|
||||||
) -> Mapping[str, Optional[RoomsForUser]]:
|
) -> Mapping[str, Optional[RoomsForUser]]:
|
||||||
"""
|
"""
|
||||||
|
@ -907,7 +884,7 @@ class SlidingSyncRoomLists:
|
||||||
user: UserID,
|
user: UserID,
|
||||||
to_token: StreamToken,
|
to_token: StreamToken,
|
||||||
from_token: Optional[StreamToken],
|
from_token: Optional[StreamToken],
|
||||||
) -> Dict[str, _RoomMembershipForUser]:
|
) -> Tuple[Dict[str, RoomsForUserType], AbstractSet[str], AbstractSet[str]]:
|
||||||
"""
|
"""
|
||||||
Fetch room IDs that the user has had membership in (the full room list including
|
Fetch room IDs that the user has had membership in (the full room list including
|
||||||
long-lost left rooms that will be filtered, sorted, and sliced).
|
long-lost left rooms that will be filtered, sorted, and sliced).
|
||||||
|
@ -926,8 +903,11 @@ class SlidingSyncRoomLists:
|
||||||
from_token: The point in the stream to sync from.
|
from_token: The point in the stream to sync from.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A dictionary of room IDs that the user has had membership in along with
|
A 3-tuple of:
|
||||||
membership information in that room at the time of `to_token`.
|
- A dictionary of room IDs that the user has had membership in along with
|
||||||
|
membership information in that room at the time of `to_token`.
|
||||||
|
- Set of newly joined rooms
|
||||||
|
- Set of newly left rooms
|
||||||
"""
|
"""
|
||||||
user_id = user.to_string()
|
user_id = user.to_string()
|
||||||
|
|
||||||
|
@ -944,12 +924,14 @@ class SlidingSyncRoomLists:
|
||||||
|
|
||||||
# If the user has never joined any rooms before, we can just return an empty list
|
# If the user has never joined any rooms before, we can just return an empty list
|
||||||
if not room_for_user_list:
|
if not room_for_user_list:
|
||||||
return {}
|
return {}, set(), set()
|
||||||
|
|
||||||
# Since we fetched the users room list at some point in time after the
|
# Since we fetched the users room list at some point in time after the
|
||||||
# tokens, we need to revert/rewind some membership changes to match the point in
|
# tokens, we need to revert/rewind some membership changes to match the point in
|
||||||
# time of the `to_token`.
|
# time of the `to_token`.
|
||||||
rooms_for_user = {room.room_id: room for room in room_for_user_list}
|
rooms_for_user: Dict[str, RoomsForUserType] = {
|
||||||
|
room.room_id: room for room in room_for_user_list
|
||||||
|
}
|
||||||
changes = await self._get_rewind_changes_to_current_membership_to_token(
|
changes = await self._get_rewind_changes_to_current_membership_to_token(
|
||||||
user, rooms_for_user, to_token
|
user, rooms_for_user, to_token
|
||||||
)
|
)
|
||||||
|
@ -966,42 +948,23 @@ class SlidingSyncRoomLists:
|
||||||
user_id, to_token=to_token, from_token=from_token
|
user_id, to_token=to_token, from_token=from_token
|
||||||
)
|
)
|
||||||
|
|
||||||
dm_room_ids = await self._get_dm_rooms_for_user(user_id)
|
|
||||||
|
|
||||||
# Our working list of rooms that can show up in the sync response
|
|
||||||
sync_room_id_set = {
|
|
||||||
room_for_user.room_id: _RoomMembershipForUser(
|
|
||||||
room_id=room_for_user.room_id,
|
|
||||||
event_id=room_for_user.event_id,
|
|
||||||
event_pos=room_for_user.event_pos,
|
|
||||||
membership=room_for_user.membership,
|
|
||||||
sender=room_for_user.sender,
|
|
||||||
newly_joined=room_id in newly_joined_room_ids,
|
|
||||||
newly_left=room_id in newly_left_room_ids,
|
|
||||||
is_dm=room_id in dm_room_ids,
|
|
||||||
)
|
|
||||||
for room_id, room_for_user in rooms_for_user.items()
|
|
||||||
}
|
|
||||||
|
|
||||||
# Ensure we have entries for rooms that the user has been "state reset"
|
# Ensure we have entries for rooms that the user has been "state reset"
|
||||||
# out of. These are rooms appear in the `newly_left_rooms` map but
|
# out of. These are rooms appear in the `newly_left_rooms` map but
|
||||||
# aren't in the `rooms_for_user` map.
|
# aren't in the `rooms_for_user` map.
|
||||||
for room_id, left_event_pos in newly_left_room_ids.items():
|
for room_id, left_event_pos in newly_left_room_ids.items():
|
||||||
if room_id in sync_room_id_set:
|
if room_id in rooms_for_user:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
sync_room_id_set[room_id] = _RoomMembershipForUser(
|
rooms_for_user[room_id] = RoomsForUserStateReset(
|
||||||
room_id=room_id,
|
room_id=room_id,
|
||||||
event_id=None,
|
event_id=None,
|
||||||
event_pos=left_event_pos,
|
event_pos=left_event_pos,
|
||||||
membership=Membership.LEAVE,
|
membership=Membership.LEAVE,
|
||||||
sender=None,
|
sender=None,
|
||||||
newly_joined=False,
|
room_version_id=await self.store.get_room_version_id(room_id),
|
||||||
newly_left=True,
|
|
||||||
is_dm=room_id in dm_room_ids,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return sync_room_id_set
|
return rooms_for_user, newly_joined_room_ids, set(newly_left_room_ids)
|
||||||
|
|
||||||
@trace
|
@trace
|
||||||
async def _get_newly_joined_and_left_rooms(
|
async def _get_newly_joined_and_left_rooms(
|
||||||
|
@ -1009,7 +972,7 @@ class SlidingSyncRoomLists:
|
||||||
user_id: str,
|
user_id: str,
|
||||||
to_token: StreamToken,
|
to_token: StreamToken,
|
||||||
from_token: Optional[StreamToken],
|
from_token: Optional[StreamToken],
|
||||||
) -> Tuple[StrCollection, Mapping[str, PersistedEventPosition]]:
|
) -> Tuple[AbstractSet[str], Mapping[str, PersistedEventPosition]]:
|
||||||
"""Fetch the sets of rooms that the user newly joined or left in the
|
"""Fetch the sets of rooms that the user newly joined or left in the
|
||||||
given token range.
|
given token range.
|
||||||
|
|
||||||
|
@ -1162,8 +1125,9 @@ class SlidingSyncRoomLists:
|
||||||
async def filter_rooms_relevant_for_sync(
|
async def filter_rooms_relevant_for_sync(
|
||||||
self,
|
self,
|
||||||
user: UserID,
|
user: UserID,
|
||||||
room_membership_for_user_map: Dict[str, _RoomMembershipForUser],
|
room_membership_for_user_map: Dict[str, RoomsForUserType],
|
||||||
) -> Dict[str, _RoomMembershipForUser]:
|
newly_left_room_ids: AbstractSet[str],
|
||||||
|
) -> Dict[str, RoomsForUserType]:
|
||||||
"""
|
"""
|
||||||
Filter room IDs that should/can be listed for this user in the sync response (the
|
Filter room IDs that should/can be listed for this user in the sync response (the
|
||||||
full room list that will be further filtered, sorted, and sliced).
|
full room list that will be further filtered, sorted, and sliced).
|
||||||
|
@ -1184,6 +1148,7 @@ class SlidingSyncRoomLists:
|
||||||
Args:
|
Args:
|
||||||
user: User that is syncing
|
user: User that is syncing
|
||||||
room_membership_for_user_map: Room membership for the user
|
room_membership_for_user_map: Room membership for the user
|
||||||
|
newly_left_room_ids: The set of room IDs we have newly left
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A dictionary of room IDs that should be listed in the sync response along
|
A dictionary of room IDs that should be listed in the sync response along
|
||||||
|
@ -1198,7 +1163,7 @@ class SlidingSyncRoomLists:
|
||||||
if filter_membership_for_sync(
|
if filter_membership_for_sync(
|
||||||
user_id=user_id,
|
user_id=user_id,
|
||||||
room_membership_for_user=room_membership_for_user,
|
room_membership_for_user=room_membership_for_user,
|
||||||
newly_left=room_membership_for_user.newly_left,
|
newly_left=room_id in newly_left_room_ids,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1207,9 +1172,9 @@ class SlidingSyncRoomLists:
|
||||||
async def check_room_subscription_allowed_for_user(
|
async def check_room_subscription_allowed_for_user(
|
||||||
self,
|
self,
|
||||||
room_id: str,
|
room_id: str,
|
||||||
room_membership_for_user_map: Dict[str, _RoomMembershipForUser],
|
room_membership_for_user_map: Dict[str, RoomsForUserType],
|
||||||
to_token: StreamToken,
|
to_token: StreamToken,
|
||||||
) -> Optional[_RoomMembershipForUser]:
|
) -> Optional[RoomsForUserType]:
|
||||||
"""
|
"""
|
||||||
Check whether the user is allowed to see the room based on whether they have
|
Check whether the user is allowed to see the room based on whether they have
|
||||||
ever had membership in the room or if the room is `world_readable`.
|
ever had membership in the room or if the room is `world_readable`.
|
||||||
|
@ -1274,7 +1239,7 @@ class SlidingSyncRoomLists:
|
||||||
async def _bulk_get_stripped_state_for_rooms_from_sync_room_map(
|
async def _bulk_get_stripped_state_for_rooms_from_sync_room_map(
|
||||||
self,
|
self,
|
||||||
room_ids: StrCollection,
|
room_ids: StrCollection,
|
||||||
sync_room_map: Dict[str, _RoomMembershipForUser],
|
sync_room_map: Dict[str, RoomsForUserType],
|
||||||
) -> Dict[str, Optional[StateMap[StrippedStateEvent]]]:
|
) -> Dict[str, Optional[StateMap[StrippedStateEvent]]]:
|
||||||
"""
|
"""
|
||||||
Fetch stripped state for a list of room IDs. Stripped state is only
|
Fetch stripped state for a list of room IDs. Stripped state is only
|
||||||
|
@ -1371,7 +1336,7 @@ class SlidingSyncRoomLists:
|
||||||
"room_encryption",
|
"room_encryption",
|
||||||
],
|
],
|
||||||
room_ids: Set[str],
|
room_ids: Set[str],
|
||||||
sync_room_map: Dict[str, _RoomMembershipForUser],
|
sync_room_map: Dict[str, RoomsForUserType],
|
||||||
to_token: StreamToken,
|
to_token: StreamToken,
|
||||||
room_id_to_stripped_state_map: Dict[
|
room_id_to_stripped_state_map: Dict[
|
||||||
str, Optional[StateMap[StrippedStateEvent]]
|
str, Optional[StateMap[StrippedStateEvent]]
|
||||||
|
@ -1535,10 +1500,11 @@ class SlidingSyncRoomLists:
|
||||||
async def filter_rooms(
|
async def filter_rooms(
|
||||||
self,
|
self,
|
||||||
user: UserID,
|
user: UserID,
|
||||||
sync_room_map: Dict[str, _RoomMembershipForUser],
|
sync_room_map: Dict[str, RoomsForUserType],
|
||||||
filters: SlidingSyncConfig.SlidingSyncList.Filters,
|
filters: SlidingSyncConfig.SlidingSyncList.Filters,
|
||||||
to_token: StreamToken,
|
to_token: StreamToken,
|
||||||
) -> Dict[str, _RoomMembershipForUser]:
|
dm_room_ids: AbstractSet[str],
|
||||||
|
) -> Dict[str, RoomsForUserType]:
|
||||||
"""
|
"""
|
||||||
Filter rooms based on the sync request.
|
Filter rooms based on the sync request.
|
||||||
|
|
||||||
|
@ -1548,6 +1514,7 @@ class SlidingSyncRoomLists:
|
||||||
information in the room at the time of `to_token`.
|
information in the room at the time of `to_token`.
|
||||||
filters: Filters to apply
|
filters: Filters to apply
|
||||||
to_token: We filter based on the state of the room at this token
|
to_token: We filter based on the state of the room at this token
|
||||||
|
dm_room_ids: Set of room IDs that are DMs for the user
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A filtered dictionary of room IDs along with membership information in the
|
A filtered dictionary of room IDs along with membership information in the
|
||||||
|
@ -1567,14 +1534,14 @@ class SlidingSyncRoomLists:
|
||||||
filtered_room_id_set = {
|
filtered_room_id_set = {
|
||||||
room_id
|
room_id
|
||||||
for room_id in filtered_room_id_set
|
for room_id in filtered_room_id_set
|
||||||
if sync_room_map[room_id].is_dm
|
if room_id in dm_room_ids
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
# Only non-DM rooms please
|
# Only non-DM rooms please
|
||||||
filtered_room_id_set = {
|
filtered_room_id_set = {
|
||||||
room_id
|
room_id
|
||||||
for room_id in filtered_room_id_set
|
for room_id in filtered_room_id_set
|
||||||
if not sync_room_map[room_id].is_dm
|
if room_id not in dm_room_ids
|
||||||
}
|
}
|
||||||
|
|
||||||
if filters.spaces is not None:
|
if filters.spaces is not None:
|
||||||
|
@ -1862,9 +1829,9 @@ class SlidingSyncRoomLists:
|
||||||
@trace
|
@trace
|
||||||
async def sort_rooms(
|
async def sort_rooms(
|
||||||
self,
|
self,
|
||||||
sync_room_map: Dict[str, _RoomMembershipForUser],
|
sync_room_map: Dict[str, RoomsForUserType],
|
||||||
to_token: StreamToken,
|
to_token: StreamToken,
|
||||||
) -> List[_RoomMembershipForUser]:
|
) -> List[RoomsForUserType]:
|
||||||
"""
|
"""
|
||||||
Sort by `stream_ordering` of the last event that the user should see in the
|
Sort by `stream_ordering` of the last event that the user should see in the
|
||||||
room. `stream_ordering` is unique so we get a stable sort.
|
room. `stream_ordering` is unique so we get a stable sort.
|
||||||
|
|
|
@ -52,6 +52,20 @@ class RoomsForUserSlidingSync:
|
||||||
is_encrypted: bool
|
is_encrypted: bool
|
||||||
|
|
||||||
|
|
||||||
|
@attr.s(slots=True, frozen=True, weakref_slot=False, auto_attribs=True)
|
||||||
|
class RoomsForUserStateReset:
|
||||||
|
"""A version of `RoomsForUser` that supports optional sender and event ID
|
||||||
|
fields, to handle state resets. State resets can affect room membership
|
||||||
|
without a corresponding event so that information isn't always available."""
|
||||||
|
|
||||||
|
room_id: str
|
||||||
|
sender: Optional[str]
|
||||||
|
membership: str
|
||||||
|
event_id: Optional[str]
|
||||||
|
event_pos: PersistedEventPosition
|
||||||
|
room_version_id: str
|
||||||
|
|
||||||
|
|
||||||
@attr.s(slots=True, frozen=True, weakref_slot=False, auto_attribs=True)
|
@attr.s(slots=True, frozen=True, weakref_slot=False, auto_attribs=True)
|
||||||
class GetRoomsForUserWithStreamOrdering:
|
class GetRoomsForUserWithStreamOrdering:
|
||||||
room_id: str
|
room_id: str
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue