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

Commit

Permalink
Merge origin/develop
Browse files Browse the repository at this point in the history
  • Loading branch information
clokep committed Feb 2, 2023
1 parent 101e09b commit 443a492
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 8 deletions.
1 change: 1 addition & 0 deletions changelog.d/14962.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Improve performance when joining or sending an event large rooms.
7 changes: 1 addition & 6 deletions synapse/handlers/sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -1857,14 +1857,9 @@ async def _generate_sync_entry_for_rooms(
since_token = sync_result_builder.since_token
user_id = sync_result_builder.sync_config.user.to_string()

# If all rooms are blocked, we can skip bits of processing.
block_all_rooms = (
sync_result_builder.sync_config.filter_collection.blocks_all_rooms()
)

# 1. Start by fetching all ephemeral events in rooms we've joined (if required).
block_all_room_ephemeral = (
block_all_rooms
sync_result_builder.sync_config.filter_collection.blocks_all_rooms()
or sync_result_builder.sync_config.filter_collection.blocks_all_room_ephemeral()
)
if block_all_room_ephemeral:
Expand Down
46 changes: 44 additions & 2 deletions synapse/storage/databases/main/roommember.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
from itertools import chain
from typing import (
TYPE_CHECKING,
AbstractSet,
Expand Down Expand Up @@ -1131,12 +1132,33 @@ async def _get_joined_hosts(
else:
# The cache doesn't match the state group or prev state group,
# so we calculate the result from first principles.
#
# We need to fetch all hosts joined to the room according to `state` by
# inspecting all join memberships in `state`. However, if the `state` is
# relatively recent then many of its events are likely to be held in
# the current state of the room, which is easily available and likely
# cached.
#
# We therefore compute the set of `state` events not in the
# current state and only fetch those.
current_memberships = (
await self._get_approximate_current_memberships_in_room(room_id)
)
unknown_state_events = {}
joined_users_in_current_state = []

for (type, state_key), event_id in state.items():
if event_id not in current_memberships:
unknown_state_events[type, state_key] = event_id
elif current_memberships[event_id] == Membership.JOIN:
joined_users_in_current_state.append(state_key)

joined_user_ids = await self.get_joined_user_ids_from_state(
room_id, state
room_id, unknown_state_events
)

cache.hosts_to_joined_users = {}
for user_id in joined_user_ids:
for user_id in chain(joined_user_ids, joined_users_in_current_state):
host = intern_string(get_domain_from_id(user_id))
cache.hosts_to_joined_users.setdefault(host, set()).add(user_id)

Expand All @@ -1147,6 +1169,26 @@ async def _get_joined_hosts(

return frozenset(cache.hosts_to_joined_users)

async def _get_approximate_current_memberships_in_room(
self, room_id: str
) -> Mapping[str, Optional[str]]:
"""Build a map from event id to membership, for all events in the current state.
The event ids of non-memberships events (e.g. `m.room.power_levels`) are present
in the result, mapped to values of `None`.
The result is approximate for partially-joined rooms. It is fully accurate
for fully-joined rooms.
"""

rows = await self.db_pool.simple_select_list(
"current_state_events",
keyvalues={"room_id": room_id},
retcols=("event_id", "membership"),
desc="has_completed_background_updates",
)
return {row["event_id"]: row["membership"] for row in rows}

@cached(max_entries=10000)
def _get_joined_hosts_cache(self, room_id: str) -> "_JoinedHostsCache":
return _JoinedHostsCache()
Expand Down

0 comments on commit 443a492

Please sign in to comment.