summary refs log tree commit diff
path: root/synapse/storage/databases/main/purge_events.py
diff options
context:
space:
mode:
authorErik Johnston <erik@matrix.org>2022-05-03 11:47:21 +0100
committerGitHub <noreply@github.com>2022-05-03 11:47:21 +0100
commitae7858f184f4fd1533d0a5dd70174e3c70f529ad (patch)
tree2227320390fb7919e2f2f141c952099fa67066cd /synapse/storage/databases/main/purge_events.py
parentPrune mypy ignore_missing_imports list (#12608) (diff)
downloadsynapse-ae7858f184f4fd1533d0a5dd70174e3c70f529ad.tar.xz
Fix race when persisting an event and deleting a room (#12594)
This works by taking a row level lock on the `rooms` table at the start of both transactions, ensuring that they don't run at the same time. In the event persistence transaction we also check that there is an entry still in the `rooms` table.

I can't figure out how to do this in SQLite. I was just going to lock the table, but it seems that we don't support that in SQLite either, so I'm *really* confused as to how we maintain integrity in SQLite when using `lock_table`....
Diffstat (limited to 'synapse/storage/databases/main/purge_events.py')
-rw-r--r--synapse/storage/databases/main/purge_events.py8
1 files changed, 6 insertions, 2 deletions
diff --git a/synapse/storage/databases/main/purge_events.py b/synapse/storage/databases/main/purge_events.py
index 2e3818e432..bfc85b3add 100644
--- a/synapse/storage/databases/main/purge_events.py
+++ b/synapse/storage/databases/main/purge_events.py
@@ -324,7 +324,12 @@ class PurgeEventsStore(StateGroupWorkerStore, CacheInvalidationWorkerStore):
         )
 
     def _purge_room_txn(self, txn: LoggingTransaction, room_id: str) -> List[int]:
-        # First we fetch all the state groups that should be deleted, before
+        # We *immediately* delete the room from the rooms table. This ensures
+        # that we don't race when persisting events (as that transaction checks
+        # that the room exists).
+        txn.execute("DELETE FROM rooms WHERE room_id = ?", (room_id,))
+
+        # Next, we fetch all the state groups that should be deleted, before
         # we delete that information.
         txn.execute(
             """
@@ -403,7 +408,6 @@ class PurgeEventsStore(StateGroupWorkerStore, CacheInvalidationWorkerStore):
             "room_stats_state",
             "room_stats_current",
             "room_stats_earliest_token",
-            "rooms",
             "stream_ordering_to_exterm",
             "users_in_public_rooms",
             "users_who_share_private_rooms",