From c10b78469f84aa67828b6c6160ed4724405db615 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Fri, 12 Dec 2025 14:22:00 +0000 Subject: [PATCH] Prune sliding_sync_connection_required_state --- .../storage/databases/main/sliding_sync.py | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/synapse/storage/databases/main/sliding_sync.py b/synapse/storage/databases/main/sliding_sync.py index c66002dae4..3c32550e97 100644 --- a/synapse/storage/databases/main/sliding_sync.py +++ b/synapse/storage/databases/main/sliding_sync.py @@ -450,6 +450,9 @@ class SlidingSyncStore(SQLBaseStore): # Now that we have seen the client has received and used the connection # position, we can delete all the other connection positions. + # + # Note: the rest of the code here assumes this is the only remaining + # connection position. sql = """ DELETE FROM sliding_sync_connection_positions WHERE connection_key = ? AND connection_position != ? @@ -515,6 +518,41 @@ class SlidingSyncStore(SQLBaseStore): required_state_map=required_state_map[required_state_id], ) + # Clean up any required state IDs that are no longer used by any + # connection position on this connection. + # + # We store the required state config per-connection per-room. Since this + # can be a lot of data, we deduplicate the required state JSON and store + # it separately, with multiple rooms referencing the same required state + # ID. Over time as the required state configs change, some required + # state IDs may no longer be referenced by any room config, so we need + # to clean them up. + # + # We do this by noting that we have pulled out *all* rows from + # `sliding_sync_connection_required_state` for this connection above. We + # have also pulled out all referenced required state IDs for *this* + # connection position, which is the only connection position that + # remains (we deleted the others above). + # + # Thus we can compute the unused required state IDs by looking for any + # required state IDs that are not referenced by the remaining connection + # position. + used_required_state_ids = { + required_state_id for _, _, required_state_id in room_config_rows + } + + unused_required_state_ids = required_state_map.keys() - used_required_state_ids + if unused_required_state_ids: + self.db_pool.simple_delete_many_batch_txn( + txn, + table="sliding_sync_connection_required_state", + keys=("connection_key", "required_state_id"), + values=[ + (connection_key, required_state_id) + for required_state_id in unused_required_state_ids + ], + ) + # Now look up the per-room stream data. rooms: dict[str, HaveSentRoom[str]] = {} receipts: dict[str, HaveSentRoom[str]] = {}