Skip to content

Commit 8cdd2d2

Browse files
Fix bug in sliding sync when using old DB. (#17398)
We don't necessarily have `instance_name` for old events (before we support multiple event persisters). We treat those as if the `instance_name` was "master". --------- Co-authored-by: Eric Eastwood <[email protected]>
1 parent 3fef535 commit 8cdd2d2

File tree

8 files changed

+33
-212
lines changed

8 files changed

+33
-212
lines changed

changelog.d/17398.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix bug in experimental [MSC3575](https://github.com/matrix-org/matrix-spec-proposals/pull/3575) Sliding Sync `/sync` endpoint when using an old database.

synapse/storage/_base.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,6 @@ def _invalidate_state_caches(
119119
self._attempt_to_invalidate_cache(
120120
"get_user_in_room_with_profile", (room_id, user_id)
121121
)
122-
self._attempt_to_invalidate_cache(
123-
"get_rooms_for_user_with_stream_ordering", (user_id,)
124-
)
125122
self._attempt_to_invalidate_cache("get_rooms_for_user", (user_id,))
126123

127124
# Purge other caches based on room state.
@@ -148,9 +145,6 @@ def _invalidate_state_caches_all(self, room_id: str) -> None:
148145
self._attempt_to_invalidate_cache("get_local_users_in_room", (room_id,))
149146
self._attempt_to_invalidate_cache("does_pair_of_users_share_a_room", None)
150147
self._attempt_to_invalidate_cache("get_user_in_room_with_profile", None)
151-
self._attempt_to_invalidate_cache(
152-
"get_rooms_for_user_with_stream_ordering", None
153-
)
154148
self._attempt_to_invalidate_cache("get_rooms_for_user", None)
155149
self._attempt_to_invalidate_cache("get_room_summary", (room_id,))
156150

synapse/storage/databases/main/cache.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -268,16 +268,12 @@ def _process_event_stream_row(self, token: int, row: EventsStreamRow) -> None:
268268
self._curr_state_delta_stream_cache.entity_has_changed(data.room_id, token) # type: ignore[attr-defined]
269269

270270
if data.type == EventTypes.Member:
271-
self.get_rooms_for_user_with_stream_ordering.invalidate( # type: ignore[attr-defined]
272-
(data.state_key,)
273-
)
274271
self.get_rooms_for_user.invalidate((data.state_key,)) # type: ignore[attr-defined]
275272
elif row.type == EventsStreamAllStateRow.TypeId:
276273
assert isinstance(data, EventsStreamAllStateRow)
277274
# Similar to the above, but the entire caches are invalidated. This is
278275
# unfortunate for the membership caches, but should recover quickly.
279276
self._curr_state_delta_stream_cache.entity_has_changed(data.room_id, token) # type: ignore[attr-defined]
280-
self.get_rooms_for_user_with_stream_ordering.invalidate_all() # type: ignore[attr-defined]
281277
self.get_rooms_for_user.invalidate_all() # type: ignore[attr-defined]
282278
else:
283279
raise Exception("Unknown events stream row type %s" % (row.type,))
@@ -334,9 +330,6 @@ def _invalidate_caches_for_event(
334330
self._attempt_to_invalidate_cache(
335331
"get_invited_rooms_for_local_user", (state_key,)
336332
)
337-
self._attempt_to_invalidate_cache(
338-
"get_rooms_for_user_with_stream_ordering", (state_key,)
339-
)
340333
self._attempt_to_invalidate_cache("get_rooms_for_user", (state_key,))
341334

342335
self._attempt_to_invalidate_cache(
@@ -399,9 +392,6 @@ def _invalidate_caches_for_room_events(self, room_id: str) -> None:
399392
self._attempt_to_invalidate_cache("get_thread_id", None)
400393
self._attempt_to_invalidate_cache("get_thread_id_for_receipts", None)
401394
self._attempt_to_invalidate_cache("get_invited_rooms_for_local_user", None)
402-
self._attempt_to_invalidate_cache(
403-
"get_rooms_for_user_with_stream_ordering", None
404-
)
405395
self._attempt_to_invalidate_cache("get_rooms_for_user", None)
406396
self._attempt_to_invalidate_cache("did_forget", None)
407397
self._attempt_to_invalidate_cache("get_forgotten_rooms_for_user", None)

synapse/storage/databases/main/events_worker.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1457,7 +1457,8 @@ def _fetch_event_rows(
14571457
event_dict[event_id] = _EventRow(
14581458
event_id=event_id,
14591459
stream_ordering=row[1],
1460-
instance_name=row[2],
1460+
# If instance_name is null we default to "master"
1461+
instance_name=row[2] or "master",
14611462
internal_metadata=row[3],
14621463
json=row[4],
14631464
format_version=row[5],

synapse/storage/databases/main/roommember.py

Lines changed: 6 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,7 @@
5050
from synapse.storage.databases.main.cache import CacheInvalidationWorkerStore
5151
from synapse.storage.databases.main.events_worker import EventsWorkerStore
5252
from synapse.storage.engines import Sqlite3Engine
53-
from synapse.storage.roommember import (
54-
GetRoomsForUserWithStreamOrdering,
55-
MemberSummary,
56-
ProfileInfo,
57-
RoomsForUser,
58-
)
53+
from synapse.storage.roommember import MemberSummary, ProfileInfo, RoomsForUser
5954
from synapse.types import (
6055
JsonDict,
6156
PersistedEventPosition,
@@ -494,7 +489,11 @@ def _get_rooms_for_local_user_where_membership_is_txn(
494489
sender=sender,
495490
membership=membership,
496491
event_id=event_id,
497-
event_pos=PersistedEventPosition(instance_name, stream_ordering),
492+
event_pos=PersistedEventPosition(
493+
# If instance_name is null we default to "master"
494+
instance_name or "master",
495+
stream_ordering,
496+
),
498497
room_version_id=room_version,
499498
)
500499
for room_id, sender, membership, event_id, instance_name, stream_ordering, room_version in txn
@@ -606,53 +605,6 @@ async def get_local_current_membership_for_user_in_room(
606605

607606
return results
608607

609-
@cached(max_entries=500000, iterable=True)
610-
async def get_rooms_for_user_with_stream_ordering(
611-
self, user_id: str
612-
) -> FrozenSet[GetRoomsForUserWithStreamOrdering]:
613-
"""Returns a set of room_ids the user is currently joined to.
614-
615-
If a remote user only returns rooms this server is currently
616-
participating in.
617-
618-
Args:
619-
user_id
620-
621-
Returns:
622-
Returns the rooms the user is in currently, along with the stream
623-
ordering of the most recent join for that user and room, along with
624-
the room version of the room.
625-
"""
626-
return await self.db_pool.runInteraction(
627-
"get_rooms_for_user_with_stream_ordering",
628-
self._get_rooms_for_user_with_stream_ordering_txn,
629-
user_id,
630-
)
631-
632-
def _get_rooms_for_user_with_stream_ordering_txn(
633-
self, txn: LoggingTransaction, user_id: str
634-
) -> FrozenSet[GetRoomsForUserWithStreamOrdering]:
635-
# We use `current_state_events` here and not `local_current_membership`
636-
# as a) this gets called with remote users and b) this only gets called
637-
# for rooms the server is participating in.
638-
sql = """
639-
SELECT room_id, e.instance_name, e.stream_ordering
640-
FROM current_state_events AS c
641-
INNER JOIN events AS e USING (room_id, event_id)
642-
WHERE
643-
c.type = 'm.room.member'
644-
AND c.state_key = ?
645-
AND c.membership = ?
646-
"""
647-
648-
txn.execute(sql, (user_id, Membership.JOIN))
649-
return frozenset(
650-
GetRoomsForUserWithStreamOrdering(
651-
room_id, PersistedEventPosition(instance, stream_id)
652-
)
653-
for room_id, instance, stream_id in txn
654-
)
655-
656608
async def get_users_server_still_shares_room_with(
657609
self, user_ids: Collection[str]
658610
) -> Set[str]:
@@ -701,13 +653,6 @@ async def get_rooms_for_user(self, user_id: str) -> FrozenSet[str]:
701653
If a remote user only returns rooms this server is currently
702654
participating in.
703655
"""
704-
rooms = self.get_rooms_for_user_with_stream_ordering.cache.get_immediate(
705-
(user_id,),
706-
None,
707-
update_metrics=False,
708-
)
709-
if rooms:
710-
return frozenset(r.room_id for r in rooms)
711656

712657
room_ids = await self.db_pool.simple_select_onecol(
713658
table="current_state_events",

synapse/storage/databases/main/stream.py

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ def _make_generic_sql_bound(
371371
def _filter_results(
372372
lower_token: Optional[RoomStreamToken],
373373
upper_token: Optional[RoomStreamToken],
374-
instance_name: str,
374+
instance_name: Optional[str],
375375
topological_ordering: int,
376376
stream_ordering: int,
377377
) -> bool:
@@ -384,8 +384,14 @@ def _filter_results(
384384
position maps, which we handle by fetching more than necessary from the DB
385385
and then filtering (rather than attempting to construct a complicated SQL
386386
query).
387+
388+
The `instance_name` arg is optional to handle historic rows, and is
389+
interpreted as if it was "master".
387390
"""
388391

392+
if instance_name is None:
393+
instance_name = "master"
394+
389395
event_historical_tuple = (
390396
topological_ordering,
391397
stream_ordering,
@@ -420,7 +426,7 @@ def _filter_results(
420426
def _filter_results_by_stream(
421427
lower_token: Optional[RoomStreamToken],
422428
upper_token: Optional[RoomStreamToken],
423-
instance_name: str,
429+
instance_name: Optional[str],
424430
stream_ordering: int,
425431
) -> bool:
426432
"""
@@ -436,7 +442,14 @@ def _filter_results_by_stream(
436442
position maps, which we handle by fetching more than necessary from the DB
437443
and then filtering (rather than attempting to construct a complicated SQL
438444
query).
445+
446+
The `instance_name` arg is optional to handle historic rows, and is
447+
interpreted as if it was "master".
439448
"""
449+
450+
if instance_name is None:
451+
instance_name = "master"
452+
440453
if lower_token:
441454
assert lower_token.topological is None
442455

@@ -912,7 +925,6 @@ def f(txn: LoggingTransaction) -> List[CurrentStateDeltaMembership]:
912925
prev_sender,
913926
) in txn:
914927
assert room_id is not None
915-
assert instance_name is not None
916928
assert stream_ordering is not None
917929

918930
if _filter_results_by_stream(
@@ -936,7 +948,8 @@ def f(txn: LoggingTransaction) -> List[CurrentStateDeltaMembership]:
936948
# Event
937949
event_id=event_id,
938950
event_pos=PersistedEventPosition(
939-
instance_name=instance_name,
951+
# If instance_name is null we default to "master"
952+
instance_name=instance_name or "master",
940953
stream=stream_ordering,
941954
),
942955
# When `s.event_id = null`, we won't be able to get respective
@@ -952,13 +965,11 @@ def f(txn: LoggingTransaction) -> List[CurrentStateDeltaMembership]:
952965
prev_event_id=prev_event_id,
953966
prev_event_pos=(
954967
PersistedEventPosition(
955-
instance_name=prev_instance_name,
968+
# If instance_name is null we default to "master"
969+
instance_name=prev_instance_name or "master",
956970
stream=prev_stream_ordering,
957971
)
958-
if (
959-
prev_instance_name is not None
960-
and prev_stream_ordering is not None
961-
)
972+
if (prev_stream_ordering is not None)
962973
else None
963974
),
964975
prev_membership=prev_membership,
@@ -1270,7 +1281,9 @@ def get_last_event_pos_in_room_before_stream_ordering_txn(
12701281
stream_ordering=stream_ordering,
12711282
):
12721283
return event_id, PersistedEventPosition(
1273-
instance_name, stream_ordering
1284+
# If instance_name is null we default to "master"
1285+
instance_name or "master",
1286+
stream_ordering,
12741287
)
12751288

12761289
return None

tests/handlers/test_sync.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,6 @@ def test_unknown_room_version(self) -> None:
210210
)
211211

212212
# Blow away caches (supported room versions can only change due to a restart).
213-
self.store.get_rooms_for_user_with_stream_ordering.invalidate_all()
214213
self.store.get_rooms_for_user.invalidate_all()
215214
self.store._get_event_cache.clear()
216215
self.store._event_ref.clear()

0 commit comments

Comments
 (0)