From bb80894391c5d62ffdf1e6b47e6ea22f264e1124 Mon Sep 17 00:00:00 2001
From: Erik Johnston <erikj@element.io>
Date: Thu, 29 Aug 2024 16:58:53 +0100
Subject: [PATCH] Fix background update for sliding sync (#17631)

This reverts commit ab414f2ab8a294fbffb417003eeea0f14bbd6588.

Introduced in https://github.com/element-hq/synapse/pull/17599
---
 changelog.d/17631.misc                        |  1 +
 .../databases/main/events_bg_updates.py       | 31 ++++++++++++-------
 tests/storage/test_sliding_sync_tables.py     | 10 +++---
 3 files changed, 24 insertions(+), 18 deletions(-)
 create mode 100644 changelog.d/17631.misc

diff --git a/changelog.d/17631.misc b/changelog.d/17631.misc
new file mode 100644
index 0000000000..2f81356d12
--- /dev/null
+++ b/changelog.d/17631.misc
@@ -0,0 +1 @@
+Store sliding sync per-connection state in the database.
diff --git a/synapse/storage/databases/main/events_bg_updates.py b/synapse/storage/databases/main/events_bg_updates.py
index 88ff5aa2df..3160e12bb3 100644
--- a/synapse/storage/databases/main/events_bg_updates.py
+++ b/synapse/storage/databases/main/events_bg_updates.py
@@ -1961,27 +1961,33 @@ class EventsBackgroundUpdatesStore(StreamWorkerStore, StateDeltasStore, SQLBaseS
                 return 0
 
         def _find_previous_membership_txn(
-            txn: LoggingTransaction, event_id: str, user_id: str
+            txn: LoggingTransaction, room_id: str, user_id: str, stream_ordering: int
         ) -> Tuple[str, str]:
-            # Find the previous invite/knock event before the leave event. This
-            # is done by looking at the auth events of the invite/knock and
-            # finding the corresponding membership event.
+            # Find the previous invite/knock event before the leave event
             txn.execute(
                 """
-                SELECT m.event_id, m.membership
-                FROM event_auth AS a
-                INNER JOIN room_memberships AS m ON (a.auth_id = m.event_id)
-                WHERE a.event_id = ? AND m.user_id = ?
+                SELECT event_id, membership
+                FROM room_memberships
+                WHERE
+                    room_id = ?
+                    AND user_id = ?
+                    AND event_stream_ordering < ?
+                ORDER BY event_stream_ordering DESC
+                LIMIT 1
                 """,
-                (event_id, user_id),
+                (
+                    room_id,
+                    user_id,
+                    stream_ordering,
+                ),
             )
             row = txn.fetchone()
 
             # We should see a corresponding previous invite/knock event
             assert row is not None
-            previous_event_id, membership = row
+            event_id, membership = row
 
-            return previous_event_id, membership
+            return event_id, membership
 
         # Map from (room_id, user_id) to ...
         to_insert_membership_snapshots: Dict[
@@ -2097,8 +2103,9 @@ class EventsBackgroundUpdatesStore(StreamWorkerStore, StateDeltasStore, SQLBaseS
                         await self.db_pool.runInteraction(
                             "sliding_sync_membership_snapshots_bg_update._find_previous_membership",
                             _find_previous_membership_txn,
-                            membership_event_id,
+                            room_id,
                             user_id,
+                            membership_event_stream_ordering,
                         )
                     )
 
diff --git a/tests/storage/test_sliding_sync_tables.py b/tests/storage/test_sliding_sync_tables.py
index 4be098b6f6..d0bbc1c803 100644
--- a/tests/storage/test_sliding_sync_tables.py
+++ b/tests/storage/test_sliding_sync_tables.py
@@ -270,7 +270,9 @@ class SlidingSyncTablesTestCaseBase(HomeserverTestCase):
         return invite_room_id, persisted_event
 
     def _retract_remote_invite_for_user(
-        self, user_id: str, remote_room_id: str, invite_event_id: str
+        self,
+        user_id: str,
+        remote_room_id: str,
     ) -> EventBase:
         """
         Create a fake invite retraction for a remote room and persist it.
@@ -283,7 +285,6 @@ class SlidingSyncTablesTestCaseBase(HomeserverTestCase):
             user_id: The person who was invited and we're going to retract the
                 invite for.
             remote_room_id: The room ID that the invite was for.
-            invite_event_id: The event ID of the invite
 
         Returns:
             The persisted leave (kick) event.
@@ -297,7 +298,7 @@ class SlidingSyncTablesTestCaseBase(HomeserverTestCase):
             "origin_server_ts": 1,
             "type": EventTypes.Member,
             "content": {"membership": Membership.LEAVE},
-            "auth_events": [invite_event_id],
+            "auth_events": [],
             "prev_events": [],
         }
 
@@ -2346,7 +2347,6 @@ class SlidingSyncTablesTestCase(SlidingSyncTablesTestCaseBase):
         remote_invite_retraction_event = self._retract_remote_invite_for_user(
             user_id=user1_id,
             remote_room_id=remote_invite_room_id,
-            invite_event_id=remote_invite_event.event_id,
         )
 
         # No one local is joined to the remote room
@@ -3580,7 +3580,6 @@ class SlidingSyncTablesBackgroundUpdatesTestCase(SlidingSyncTablesTestCaseBase):
         room_id_no_info_leave_event = self._retract_remote_invite_for_user(
             user_id=user1_id,
             remote_room_id=room_id_no_info,
-            invite_event_id=room_id_no_info_invite_event.event_id,
         )
         room_id_with_info_leave_event_response = self.helper.leave(
             room_id_with_info, user1_id, tok=user1_tok
@@ -3588,7 +3587,6 @@ class SlidingSyncTablesBackgroundUpdatesTestCase(SlidingSyncTablesTestCaseBase):
         space_room_id_leave_event = self._retract_remote_invite_for_user(
             user_id=user1_id,
             remote_room_id=space_room_id,
-            invite_event_id=space_room_id_invite_event.event_id,
         )
 
         # Clean-up the `sliding_sync_membership_snapshots` table as if the inserts did not