summary refs log tree commit diff
diff options
context:
space:
mode:
authorEric Eastwood <eric.eastwood@beta.gouv.fr>2024-08-06 16:50:14 -0500
committerEric Eastwood <eric.eastwood@beta.gouv.fr>2024-08-06 16:50:14 -0500
commit2f3bd272840914d1aa6d88e9ec250bc1d95ceafd (patch)
tree0b499083b2db022038a3b969baab19b312cea226
parentSpecial treatment for boolean columns (diff)
downloadsynapse-2f3bd272840914d1aa6d88e9ec250bc1d95ceafd.tar.xz
Test is running
-rw-r--r--synapse/storage/databases/main/events.py36
-rw-r--r--synapse/storage/schema/__init__.py5
-rw-r--r--synapse/storage/schema/main/delta/87/01_sliding_sync_memberships.sql21
-rw-r--r--tests/storage/test_events.py31
4 files changed, 68 insertions, 25 deletions
diff --git a/synapse/storage/databases/main/events.py b/synapse/storage/databases/main/events.py
index 3a0eebe411..ea382b0b30 100644
--- a/synapse/storage/databases/main/events.py
+++ b/synapse/storage/databases/main/events.py
@@ -1330,20 +1330,20 @@ class PersistEventsStore:
             insert_keys = sliding_sync_joined_rooms_insert_map.keys()
             insert_values = sliding_sync_joined_rooms_insert_map.values()
             if len(insert_keys) > 0:
-                # TODO: Should we add `bump_stamp` on insert?
+                # TODO: Should we add `event_stream_ordering`, `bump_stamp` on insert?
                 txn.execute(
                     f"""
                     INSERT INTO sliding_sync_joined_rooms
-                        (room_id, event_stream_ordering, {", ".join(insert_keys)})
+                        (room_id, {", ".join(insert_keys)})
                     VALUES (
                         ?,
-                        (SELECT stream_ordering FROM events WHERE event_id = ?)
                         {", ".join("?" for _ in insert_values)}
                     )
                     ON CONFLICT (room_id)
                     DO UPDATE SET
                         {", ".join(f"{key} = EXCLUDED.{key}" for key in insert_keys)}
                     """,
+                    [room_id] + list(insert_values),
                 )
 
         # We now update `local_current_membership`. We do this regardless
@@ -1386,12 +1386,15 @@ class PersistEventsStore:
         # whether the server is still in the room or not because we still want a row if
         # a local user was just left/kicked or got banned from the room.
         if to_insert:
-            membership_event_ids: List[str] = []
+            membership_event_id_to_user_id_map: Dict[str, str] = {}
             for state_key, event_id in to_insert.items():
                 if state_key[0] == EventTypes.Member and self.is_mine_id(state_key[1]):
-                    membership_event_ids.append(event_id)
+                    membership_event_id_to_user_id_map[event_id] = state_key[1]
 
             # Fetch the events from the database
+            #
+            # TODO: We should gather this data before we delete the
+            # `current_state_events` in a `no_longer_in_room` situation.
             (
                 event_type_and_state_key_in_list_clause,
                 event_type_and_state_key_args,
@@ -1406,11 +1409,11 @@ class PersistEventsStore:
             )
             txn.execute(
                 f"""
-                SELECT event_id, type, state_key, json
-                FROM current_state_events
-                INNER JOIN event_json USING (event_id)
+                SELECT c.event_id, c.type, c.state_key, j.json
+                FROM current_state_events AS c
+                INNER JOIN event_json AS j USING (event_id)
                 WHERE
-                    room_id = ?
+                    c.room_id = ?
                     AND {event_type_and_state_key_in_list_clause}
                 """,
                 [room_id] + event_type_and_state_key_args,
@@ -1451,6 +1454,8 @@ class PersistEventsStore:
             insert_values = sliding_sync_non_joined_rooms_insert_map.values()
             # We `DO NOTHING` on conflict because if the row is already in the database,
             # we just assume that it was already processed (values should be the same anyways).
+            #
+            # TODO: Only do this for non-join membership
             txn.execute_batch(
                 f"""
                 INSERT INTO sliding_sync_non_join_memberships
@@ -1458,21 +1463,22 @@ class PersistEventsStore:
                 VALUES (
                     ?, ?, ?,
                     (SELECT membership FROM room_memberships WHERE event_id = ?),
-                    (SELECT stream_ordering FROM events WHERE event_id = ?)
+                    (SELECT stream_ordering FROM events WHERE event_id = ?),
                     {", ".join("?" for _ in insert_values)}
                 )
-                ON CONFLICT (room_id)
+                ON CONFLICT (room_id, membership_event_id)
                 DO NOTHING
                 """,
                 [
-                    (
+                    [
                         room_id,
                         membership_event_id,
-                        state_key[1],
+                        user_id,
                         membership_event_id,
                         membership_event_id,
-                    )
-                    for membership_event_id in membership_event_ids
+                    ]
+                    + list(insert_values)
+                    for membership_event_id, user_id in membership_event_id_to_user_id_map.items()
                 ],
             )
 
diff --git a/synapse/storage/schema/__init__.py b/synapse/storage/schema/__init__.py
index 581d00346b..8279002439 100644
--- a/synapse/storage/schema/__init__.py
+++ b/synapse/storage/schema/__init__.py
@@ -19,7 +19,7 @@
 #
 #
 
-SCHEMA_VERSION = 86  # remember to update the list below when updating
+SCHEMA_VERSION = 87  # remember to update the list below when updating
 """Represents the expectations made by the codebase about the database schema
 
 This should be incremented whenever the codebase changes its requirements on the
@@ -142,6 +142,9 @@ Changes in SCHEMA_VERSION = 85
 
 Changes in SCHEMA_VERSION = 86
     - Add a column `authenticated` to the tables `local_media_repository` and `remote_media_cache`
+
+Changes in SCHEMA_VERSION = 87
+    - TODO
 """
 
 
diff --git a/synapse/storage/schema/main/delta/87/01_sliding_sync_memberships.sql b/synapse/storage/schema/main/delta/87/01_sliding_sync_memberships.sql
index efbc5ebd1e..d496a5a91a 100644
--- a/synapse/storage/schema/main/delta/87/01_sliding_sync_memberships.sql
+++ b/synapse/storage/schema/main/delta/87/01_sliding_sync_memberships.sql
@@ -17,11 +17,11 @@
 --
 -- This table is kept in sync with `current_state_events`
 CREATE TABLE IF NOT EXISTS sliding_sync_joined_rooms(
-    FOREIGN KEY(room_id) REFERENCES rooms(room_id),
+    room_id TEXT NOT NULL REFERENCES rooms(room_id),
     -- The `stream_ordering` of the latest event in the room
-    event_stream_ordering BIGINT REFERENCES events(stream_ordering)
+    event_stream_ordering BIGINT REFERENCES events(stream_ordering),
     -- The `stream_ordering` of the last event according to the `bump_event_types`
-    bump_stamp: BIGINT,
+    bump_stamp BIGINT,
     -- `m.room.create` -> `content.type`
     room_type TEXT,
     -- `m.room.name` -> `content.name`
@@ -35,17 +35,20 @@ CREATE TABLE IF NOT EXISTS sliding_sync_joined_rooms(
 -- We don't include `bump_stamp` here because we can just use the `stream_ordering` from
 -- the membership event itself as the `bump_stamp`.
 CREATE TABLE IF NOT EXISTS sliding_sync_non_join_memberships(
-    FOREIGN KEY(room_id) REFERENCES rooms(room_id),
-    FOREIGN KEY(membership_event_id) REFERENCES events(event_id),
+    room_id TEXT NOT NULL REFERENCES rooms(room_id),
+    membership_event_id TEXT NOT NULL REFERENCES events(event_id),
     user_id TEXT NOT NULL,
     membership TEXT NOT NULL,
     -- `stream_ordering` of the `membership_event_id`
-    event_stream_ordering BIGINT REFERENCES events(stream_ordering)
-    -- `m.room.create` -> `content.type`
+    event_stream_ordering BIGINT REFERENCES events(stream_ordering),
+    -- `m.room.create` -> `content.type` (according to the current state at the time of
+    -- the membership)
     room_type TEXT,
-    -- `m.room.name` -> `content.name`
+    -- `m.room.name` -> `content.name` (according to the current state at the time of
+    -- the membership)
     room_name TEXT,
-    -- `m.room.encryption` -> `content.algorithm`
+    -- `m.room.encryption` -> `content.algorithm` (according to the current state at the
+    -- time of the membership)
     is_encrypted BOOLEAN,
     PRIMARY KEY (room_id, membership_event_id)
 );
diff --git a/tests/storage/test_events.py b/tests/storage/test_events.py
index 0a7c4c9421..bc37acfea7 100644
--- a/tests/storage/test_events.py
+++ b/tests/storage/test_events.py
@@ -19,6 +19,7 @@
 #
 #
 
+import logging
 from typing import List, Optional
 
 from twisted.test.proto_helpers import MemoryReactor
@@ -35,6 +36,8 @@ from synapse.util import Clock
 
 from tests.unittest import HomeserverTestCase
 
+logger = logging.getLogger(__name__)
+
 
 class ExtremPruneTestCase(HomeserverTestCase):
     servlets = [
@@ -481,3 +484,31 @@ class InvalideUsersInRoomCacheTestCase(HomeserverTestCase):
 
         users = self.get_success(self.store.get_users_in_room(room_id))
         self.assertEqual(users, [])
+
+
+class SlidingSyncPrePopulatedTablesTestCase(HomeserverTestCase):
+    """
+    Tests to make sure the
+    `sliding_sync_joined_rooms`/`sliding_sync_non_join_memberships` database tables are
+    populated correctly.
+    """
+
+    servlets = [
+        admin.register_servlets,
+        login.register_servlets,
+        room.register_servlets,
+    ]
+
+    def test_rooms_invite_shared_history_initial_sync(self) -> None:
+        """
+        TODO
+        """
+        user1_id = self.register_user("user1", "pass")
+        user1_tok = self.login(user1_id, "pass")
+        user2_id = self.register_user("user2", "pass")
+        user2_tok = self.login(user2_id, "pass")
+
+        room_id1 = self.helper.create_room_as(user2_id, tok=user2_tok)
+
+        # user1 joins the room
+        self.helper.join(room_id1, user1_id, tok=user1_tok)