-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Non lazy loading sync not blocking during fast join #14831
Changes from 10 commits
3bad02f
661e25b
b01ec64
4441f5b
33d9642
6023bee
1cca9eb
fbfafca
6472178
7b60abe
46062d8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Faster joins: non lazy-loading syncs will return immediately after a faster join, by omitting partial state rooms until we acquire their full state. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1613,9 +1613,9 @@ async def _generate_sync_entry_for_to_device( | |
now_token = sync_result_builder.now_token | ||
since_stream_id = 0 | ||
if sync_result_builder.since_token is not None: | ||
since_stream_id = int(sync_result_builder.since_token.to_device_key) | ||
since_stream_id = sync_result_builder.since_token.to_device_key | ||
|
||
if device_id is not None and since_stream_id != int(now_token.to_device_key): | ||
if device_id is not None and since_stream_id != now_token.to_device_key: | ||
messages, stream_id = await self.store.get_messages_for_device( | ||
user_id, device_id, since_stream_id, now_token.to_device_key | ||
) | ||
|
@@ -1684,7 +1684,7 @@ async def _generate_sync_entry_for_account_data( | |
) | ||
|
||
push_rules_changed = await self.store.have_push_rules_changed_for_user( | ||
user_id, int(since_token.push_rules_key) | ||
user_id, since_token.push_rules_key | ||
) | ||
|
||
if push_rules_changed: | ||
|
@@ -1817,11 +1817,35 @@ async def _generate_sync_entry_for_rooms( | |
) | ||
sync_result_builder.now_token = now_token | ||
|
||
# Retrieve rooms that got un partial stated in the meantime, only useful in case | ||
# of a non lazy-loading-members sync. | ||
# We also skip calculating that in case of initial sync since we don't need it. | ||
Comment on lines
+1820
to
+1822
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Comment: For nonlazy, incremental syncs: find all the rooms we excluded in previous nonlazy syncs that we can now disclose to the user. |
||
un_partial_stated_rooms = set() | ||
if ( | ||
since_token | ||
and not sync_result_builder.sync_config.filter_collection.lazy_load_members() | ||
): | ||
un_partial_stated_rooms_since = 0 | ||
DMRobertson marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if sync_result_builder.since_token is not None: | ||
un_partial_stated_rooms_since = ( | ||
sync_result_builder.since_token.un_partial_stated_rooms_key | ||
) | ||
|
||
un_partial_stated_rooms = ( | ||
await self.store.get_un_partial_stated_rooms_between( | ||
un_partial_stated_rooms_since, | ||
sync_result_builder.now_token.un_partial_stated_rooms_key, | ||
sync_result_builder.joined_room_ids, | ||
) | ||
) | ||
|
||
# 2. We check up front if anything has changed, if it hasn't then there is | ||
# no point in going further. | ||
if not sync_result_builder.full_state: | ||
if since_token and not ephemeral_by_room and not account_data_by_room: | ||
have_changed = await self._have_rooms_changed(sync_result_builder) | ||
have_changed = await self._have_rooms_changed( | ||
sync_result_builder, un_partial_stated_rooms | ||
) | ||
Comment on lines
+1846
to
+1848
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Every un-psed room during the sync period is considered to have "changed", i.e., client needs to be informed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rooms which are partial stated need to not sure up in a non-lazy sync. Where is this done? Should this be here? EJ: this method is better called "should_we_tell_the_client_about_this_room_lol" |
||
log_kv({"rooms_have_changed": have_changed}) | ||
if not have_changed: | ||
tags_by_room = await self.store.get_updated_tags( | ||
|
@@ -1835,7 +1859,7 @@ async def _generate_sync_entry_for_rooms( | |
ignored_users = await self.store.ignored_users(user_id) | ||
if since_token: | ||
room_changes = await self._get_rooms_changed( | ||
sync_result_builder, ignored_users | ||
sync_result_builder, ignored_users, un_partial_stated_rooms | ||
) | ||
tags_by_room = await self.store.get_updated_tags( | ||
user_id, since_token.account_data_key | ||
|
@@ -1888,7 +1912,9 @@ async def handle_room_entries(room_entry: "RoomSyncResultBuilder") -> None: | |
) | ||
|
||
async def _have_rooms_changed( | ||
self, sync_result_builder: "SyncResultBuilder" | ||
self, | ||
sync_result_builder: "SyncResultBuilder", | ||
un_partial_stated_rooms: AbstractSet[str], | ||
) -> bool: | ||
"""Returns whether there may be any new events that should be sent down | ||
the sync. Returns True if there are. | ||
|
@@ -1905,6 +1931,11 @@ async def _have_rooms_changed( | |
|
||
stream_id = since_token.room_key.stream | ||
for room_id in sync_result_builder.joined_room_ids: | ||
# If a room has been un partial stated during the sync period, | ||
# assume it has seen some kind of change. We'll process that | ||
# change later, in _get_rooms_changed. | ||
if room_id in un_partial_stated_rooms: | ||
return True | ||
if self.store.has_room_changed_since(room_id, stream_id): | ||
return True | ||
return False | ||
|
@@ -1913,6 +1944,7 @@ async def _get_rooms_changed( | |
self, | ||
sync_result_builder: "SyncResultBuilder", | ||
ignored_users: FrozenSet[str], | ||
un_partial_stated_rooms: AbstractSet[str], | ||
) -> _RoomChanges: | ||
"""Determine the changes in rooms to report to the user. | ||
|
||
|
@@ -2116,7 +2148,25 @@ async def _get_rooms_changed( | |
room_entry = room_to_events.get(room_id, None) | ||
|
||
newly_joined = room_id in newly_joined_rooms | ||
if room_entry: | ||
|
||
# Partially joined rooms are omitted from non lazy-loading-members | ||
# syncs until the resync completes and that room is fully stated. | ||
# When that happens, we need to include their full state in | ||
# the next non-lazy-loading sync. | ||
if ( | ||
not sync_config.filter_collection.lazy_load_members() | ||
and room_id in un_partial_stated_rooms | ||
): | ||
entry = RoomSyncResultBuilder( | ||
room_id=room_id, | ||
rtype="joined", | ||
events=None, | ||
DMRobertson marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. EJ: are we going to lose events There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. EJ: Does newly_joined_rooms need to be updated to include un-partial-stated rooms and exclude those which are currently partial stated? See the return value of this function |
||
newly_joined=True, | ||
full_state=True, | ||
since_token=None, | ||
upto_token=now_token, | ||
) | ||
elif room_entry: | ||
events, start_key = room_entry | ||
|
||
prev_batch_token = now_token.copy_and_replace( | ||
|
@@ -2186,6 +2236,13 @@ async def _get_all_rooms( | |
knocked = [] | ||
|
||
for event in room_list: | ||
# Do not include rooms that we don't have the full state yet | ||
# in case of non lazy-loading-members sync. | ||
if ( | ||
not sync_config.filter_collection.lazy_load_members() | ||
) and await self.store.is_partial_state_room(event.room_id): | ||
continue | ||
|
||
Comment on lines
+2239
to
+2245
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In an initial sync, we completely ignore rooms that are currently partially stated |
||
if event.room_version_id not in KNOWN_ROOM_VERSIONS: | ||
continue | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not following you here. I thought we want to exclude partially-joined rooms from all non-lazy load syncs. Why should that not also apply to an initial, non-lazy sync?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We skip calculating the rooms that got unpartialstated because in case of initial, we have another piece of code that already exclude any partial stated rooms. The stream of unpartialstated rooms is only useful to know which ones have been unpartialed between 2 syncs, for an initial sync we just directly check the DB.