Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit c2c364f

Browse files
authored
Replace room_depth.min_depth with a BIGINT (#10289)
while I'm dealing with INTEGERs and BIGINTs, let's replace room_depth.min_depth with a BIGINT.
1 parent 19d0401 commit c2c364f

File tree

4 files changed

+186
-7
lines changed

4 files changed

+186
-7
lines changed

changelog.d/10289.misc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Convert `room_depth.min_depth` column to a `BIGINT`.

synapse/storage/databases/main/room.py

Lines changed: 97 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from synapse.storage._base import SQLBaseStore, db_to_json
2626
from synapse.storage.database import DatabasePool, LoggingTransaction
2727
from synapse.storage.databases.main.search import SearchStore
28+
from synapse.storage.types import Cursor
2829
from synapse.types import JsonDict, ThirdPartyInstanceID
2930
from synapse.util import json_encoder
3031
from synapse.util.caches.descriptors import cached
@@ -1022,10 +1023,22 @@ def get_rooms_for_retention_period_in_range_txn(txn):
10221023
)
10231024

10241025

1025-
class RoomBackgroundUpdateStore(SQLBaseStore):
1026+
class _BackgroundUpdates:
10261027
REMOVE_TOMESTONED_ROOMS_BG_UPDATE = "remove_tombstoned_rooms_from_directory"
10271028
ADD_ROOMS_ROOM_VERSION_COLUMN = "add_rooms_room_version_column"
1029+
POPULATE_ROOM_DEPTH_MIN_DEPTH2 = "populate_room_depth_min_depth2"
1030+
REPLACE_ROOM_DEPTH_MIN_DEPTH = "replace_room_depth_min_depth"
1031+
1032+
1033+
_REPLACE_ROOM_DEPTH_SQL_COMMANDS = (
1034+
"DROP TRIGGER populate_min_depth2_trigger ON room_depth",
1035+
"DROP FUNCTION populate_min_depth2()",
1036+
"ALTER TABLE room_depth DROP COLUMN min_depth",
1037+
"ALTER TABLE room_depth RENAME COLUMN min_depth2 TO min_depth",
1038+
)
1039+
10281040

1041+
class RoomBackgroundUpdateStore(SQLBaseStore):
10291042
def __init__(self, database: DatabasePool, db_conn, hs):
10301043
super().__init__(database, db_conn, hs)
10311044

@@ -1037,15 +1050,25 @@ def __init__(self, database: DatabasePool, db_conn, hs):
10371050
)
10381051

10391052
self.db_pool.updates.register_background_update_handler(
1040-
self.REMOVE_TOMESTONED_ROOMS_BG_UPDATE,
1053+
_BackgroundUpdates.REMOVE_TOMESTONED_ROOMS_BG_UPDATE,
10411054
self._remove_tombstoned_rooms_from_directory,
10421055
)
10431056

10441057
self.db_pool.updates.register_background_update_handler(
1045-
self.ADD_ROOMS_ROOM_VERSION_COLUMN,
1058+
_BackgroundUpdates.ADD_ROOMS_ROOM_VERSION_COLUMN,
10461059
self._background_add_rooms_room_version_column,
10471060
)
10481061

1062+
# BG updates to change the type of room_depth.min_depth
1063+
self.db_pool.updates.register_background_update_handler(
1064+
_BackgroundUpdates.POPULATE_ROOM_DEPTH_MIN_DEPTH2,
1065+
self._background_populate_room_depth_min_depth2,
1066+
)
1067+
self.db_pool.updates.register_background_update_handler(
1068+
_BackgroundUpdates.REPLACE_ROOM_DEPTH_MIN_DEPTH,
1069+
self._background_replace_room_depth_min_depth,
1070+
)
1071+
10491072
async def _background_insert_retention(self, progress, batch_size):
10501073
"""Retrieves a list of all rooms within a range and inserts an entry for each of
10511074
them into the room_retention table.
@@ -1164,7 +1187,9 @@ def _background_add_rooms_room_version_column_txn(txn: LoggingTransaction):
11641187
new_last_room_id = room_id
11651188

11661189
self.db_pool.updates._background_update_progress_txn(
1167-
txn, self.ADD_ROOMS_ROOM_VERSION_COLUMN, {"room_id": new_last_room_id}
1190+
txn,
1191+
_BackgroundUpdates.ADD_ROOMS_ROOM_VERSION_COLUMN,
1192+
{"room_id": new_last_room_id},
11681193
)
11691194

11701195
return False
@@ -1176,7 +1201,7 @@ def _background_add_rooms_room_version_column_txn(txn: LoggingTransaction):
11761201

11771202
if end:
11781203
await self.db_pool.updates._end_background_update(
1179-
self.ADD_ROOMS_ROOM_VERSION_COLUMN
1204+
_BackgroundUpdates.ADD_ROOMS_ROOM_VERSION_COLUMN
11801205
)
11811206

11821207
return batch_size
@@ -1215,7 +1240,7 @@ def _get_rooms(txn):
12151240

12161241
if not rooms:
12171242
await self.db_pool.updates._end_background_update(
1218-
self.REMOVE_TOMESTONED_ROOMS_BG_UPDATE
1243+
_BackgroundUpdates.REMOVE_TOMESTONED_ROOMS_BG_UPDATE
12191244
)
12201245
return 0
12211246

@@ -1224,7 +1249,7 @@ def _get_rooms(txn):
12241249
await self.set_room_is_public(room_id, False)
12251250

12261251
await self.db_pool.updates._background_update_progress(
1227-
self.REMOVE_TOMESTONED_ROOMS_BG_UPDATE, {"room_id": rooms[-1]}
1252+
_BackgroundUpdates.REMOVE_TOMESTONED_ROOMS_BG_UPDATE, {"room_id": rooms[-1]}
12281253
)
12291254

12301255
return len(rooms)
@@ -1268,6 +1293,71 @@ async def has_auth_chain_index(self, room_id: str) -> bool:
12681293

12691294
return max_ordering is None
12701295

1296+
async def _background_populate_room_depth_min_depth2(
1297+
self, progress: JsonDict, batch_size: int
1298+
) -> int:
1299+
"""Populate room_depth.min_depth2
1300+
1301+
This is to deal with the fact that min_depth was initially created as a
1302+
32-bit integer field.
1303+
"""
1304+
1305+
def process(txn: Cursor) -> int:
1306+
last_room = progress.get("last_room", "")
1307+
txn.execute(
1308+
"""
1309+
UPDATE room_depth SET min_depth2=min_depth
1310+
WHERE room_id IN (
1311+
SELECT room_id FROM room_depth WHERE room_id > ?
1312+
ORDER BY room_id LIMIT ?
1313+
)
1314+
RETURNING room_id;
1315+
""",
1316+
(last_room, batch_size),
1317+
)
1318+
row_count = txn.rowcount
1319+
if row_count == 0:
1320+
return 0
1321+
last_room = max(row[0] for row in txn)
1322+
logger.info("populated room_depth up to %s", last_room)
1323+
1324+
self.db_pool.updates._background_update_progress_txn(
1325+
txn,
1326+
_BackgroundUpdates.POPULATE_ROOM_DEPTH_MIN_DEPTH2,
1327+
{"last_room": last_room},
1328+
)
1329+
return row_count
1330+
1331+
result = await self.db_pool.runInteraction(
1332+
"_background_populate_min_depth2", process
1333+
)
1334+
1335+
if result != 0:
1336+
return result
1337+
1338+
await self.db_pool.updates._end_background_update(
1339+
_BackgroundUpdates.POPULATE_ROOM_DEPTH_MIN_DEPTH2
1340+
)
1341+
return 0
1342+
1343+
async def _background_replace_room_depth_min_depth(
1344+
self, progress: JsonDict, batch_size: int
1345+
) -> int:
1346+
"""Drop the old 'min_depth' column and rename 'min_depth2' into its place."""
1347+
1348+
def process(txn: Cursor) -> None:
1349+
for sql in _REPLACE_ROOM_DEPTH_SQL_COMMANDS:
1350+
logger.info("completing room_depth migration: %s", sql)
1351+
txn.execute(sql)
1352+
1353+
await self.db_pool.runInteraction("_background_replace_room_depth", process)
1354+
1355+
await self.db_pool.updates._end_background_update(
1356+
_BackgroundUpdates.REPLACE_ROOM_DEPTH_MIN_DEPTH,
1357+
)
1358+
1359+
return 0
1360+
12711361

12721362
class RoomStore(RoomBackgroundUpdateStore, RoomWorkerStore, SearchStore):
12731363
def __init__(self, database: DatabasePool, db_conn, hs):
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/* Copyright 2021 The Matrix.org Foundation C.I.C
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
-- this index is redundant; there is another UNIQUE index on this table.
17+
DROP INDEX IF EXISTS room_depth_room;
18+
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Copyright 2021 The Matrix.org Foundation C.I.C.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""
16+
This migration handles the process of changing the type of `room_depth.min_depth` to
17+
a BIGINT.
18+
"""
19+
from synapse.storage.engines import BaseDatabaseEngine, PostgresEngine
20+
from synapse.storage.types import Cursor
21+
22+
23+
def run_create(cur: Cursor, database_engine: BaseDatabaseEngine, *args, **kwargs):
24+
if not isinstance(database_engine, PostgresEngine):
25+
# this only applies to postgres - sqlite does not distinguish between big and
26+
# little ints.
27+
return
28+
29+
# First add a new column to contain the bigger min_depth
30+
cur.execute("ALTER TABLE room_depth ADD COLUMN min_depth2 BIGINT")
31+
32+
# Create a trigger which will keep it populated.
33+
cur.execute(
34+
"""
35+
CREATE OR REPLACE FUNCTION populate_min_depth2() RETURNS trigger AS $BODY$
36+
BEGIN
37+
new.min_depth2 := new.min_depth;
38+
RETURN NEW;
39+
END;
40+
$BODY$ LANGUAGE plpgsql
41+
"""
42+
)
43+
44+
cur.execute(
45+
"""
46+
CREATE TRIGGER populate_min_depth2_trigger BEFORE INSERT OR UPDATE ON room_depth
47+
FOR EACH ROW
48+
EXECUTE PROCEDURE populate_min_depth2()
49+
"""
50+
)
51+
52+
# Start a bg process to populate it for old rooms
53+
cur.execute(
54+
"""
55+
INSERT INTO background_updates (ordering, update_name, progress_json) VALUES
56+
(6103, 'populate_room_depth_min_depth2', '{}')
57+
"""
58+
)
59+
60+
# and another to switch them over once it completes.
61+
cur.execute(
62+
"""
63+
INSERT INTO background_updates (ordering, update_name, progress_json, depends_on) VALUES
64+
(6103, 'replace_room_depth_min_depth', '{}', 'populate_room_depth2')
65+
"""
66+
)
67+
68+
69+
def run_upgrade(cur: Cursor, database_engine: BaseDatabaseEngine, *args, **kwargs):
70+
pass

0 commit comments

Comments
 (0)