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

Commit fac8a38

Browse files
authored
Properly handle unknown results for the stream change cache. (#14592)
StreamChangeCache.get_all_changed_entities can return None to signify it does not have information at the given stream position. Two callers (related to device lists and presence) were treating this response the same as an empty list (i.e. there being no updates).
1 parent 6acb6d7 commit fac8a38

File tree

3 files changed

+22
-16
lines changed

3 files changed

+22
-16
lines changed

changelog.d/14592.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix a long-standing bug where a device list update might not be sent to clients in certain circumstances.

synapse/handlers/presence.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1764,14 +1764,14 @@ async def _filter_all_presence_updates_for_user(
17641764
Returns:
17651765
A list of presence states for the given user to receive.
17661766
"""
1767+
updated_users = None
17671768
if from_key:
17681769
# Only return updates since the last sync
17691770
updated_users = self.store.presence_stream_cache.get_all_entities_changed(
17701771
from_key
17711772
)
1772-
if not updated_users:
1773-
updated_users = []
17741773

1774+
if updated_users is not None:
17751775
# Get the actual presence update for each change
17761776
users_to_state = await self.get_presence_handler().current_state_for_users(
17771777
updated_users

synapse/storage/databases/main/devices.py

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -842,12 +842,11 @@ async def get_users_whose_devices_changed(
842842
user_ids, from_key
843843
)
844844

845-
if not user_ids_to_check:
845+
# If an empty set was returned, there's nothing to do.
846+
if user_ids_to_check is not None and not user_ids_to_check:
846847
return set()
847848

848849
def _get_users_whose_devices_changed_txn(txn: LoggingTransaction) -> Set[str]:
849-
changes: Set[str] = set()
850-
851850
stream_id_where_clause = "stream_id > ?"
852851
sql_args = [from_key]
853852

@@ -858,19 +857,25 @@ def _get_users_whose_devices_changed_txn(txn: LoggingTransaction) -> Set[str]:
858857
sql = f"""
859858
SELECT DISTINCT user_id FROM device_lists_stream
860859
WHERE {stream_id_where_clause}
861-
AND
862860
"""
863861

864-
# Query device changes with a batch of users at a time
865-
# Assertion for mypy's benefit; see also
866-
# https://mypy.readthedocs.io/en/stable/common_issues.html#narrowing-and-inner-functions
867-
assert user_ids_to_check is not None
868-
for chunk in batch_iter(user_ids_to_check, 100):
869-
clause, args = make_in_list_sql_clause(
870-
txn.database_engine, "user_id", chunk
871-
)
872-
txn.execute(sql + clause, sql_args + args)
873-
changes.update(user_id for user_id, in txn)
862+
# If the stream change cache gave us no information, fetch *all*
863+
# users between the stream IDs.
864+
if user_ids_to_check is None:
865+
txn.execute(sql, sql_args)
866+
return {user_id for user_id, in txn}
867+
868+
# Otherwise, fetch changes for the given users.
869+
else:
870+
changes: Set[str] = set()
871+
872+
# Query device changes with a batch of users at a time
873+
for chunk in batch_iter(user_ids_to_check, 100):
874+
clause, args = make_in_list_sql_clause(
875+
txn.database_engine, "user_id", chunk
876+
)
877+
txn.execute(sql + " AND " + clause, sql_args + args)
878+
changes.update(user_id for user_id, in txn)
874879

875880
return changes
876881

0 commit comments

Comments
 (0)