Add a background update to clear tombstoned rooms from the directory (#6648)
* Add a background update to clear tombstoned rooms from the directory * use the ABC metaclass
This commit is contained in:
parent
9824a39d80
commit
85db7f73be
|
@ -0,0 +1 @@
|
||||||
|
Ensure that upgraded rooms are removed from the directory.
|
|
@ -166,6 +166,11 @@ class Store(
|
||||||
logger.exception("Failed to insert: %s", table)
|
logger.exception("Failed to insert: %s", table)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
def set_room_is_public(self, room_id, is_public):
|
||||||
|
raise Exception(
|
||||||
|
"Attempt to set room_is_public during port_db: database not empty?"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class MockHomeserver:
|
class MockHomeserver:
|
||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
import logging
|
import logging
|
||||||
import random
|
import random
|
||||||
|
from abc import ABCMeta
|
||||||
|
|
||||||
from six import PY2
|
from six import PY2
|
||||||
from six.moves import builtins
|
from six.moves import builtins
|
||||||
|
@ -30,7 +31,8 @@ from synapse.types import get_domain_from_id
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class SQLBaseStore(object):
|
# some of our subclasses have abstract methods, so we use the ABCMeta metaclass.
|
||||||
|
class SQLBaseStore(metaclass=ABCMeta):
|
||||||
"""Base class for data stores that holds helper functions.
|
"""Base class for data stores that holds helper functions.
|
||||||
|
|
||||||
Note that multiple instances of this class will exist as there will be one
|
Note that multiple instances of this class will exist as there will be one
|
||||||
|
|
|
@ -436,6 +436,21 @@ class BackgroundUpdater(object):
|
||||||
"background_updates", keyvalues={"update_name": update_name}
|
"background_updates", keyvalues={"update_name": update_name}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _background_update_progress(self, update_name: str, progress: dict):
|
||||||
|
"""Update the progress of a background update
|
||||||
|
|
||||||
|
Args:
|
||||||
|
update_name: The name of the background update task
|
||||||
|
progress: The progress of the update.
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self.db.runInteraction(
|
||||||
|
"background_update_progress",
|
||||||
|
self._background_update_progress_txn,
|
||||||
|
update_name,
|
||||||
|
progress,
|
||||||
|
)
|
||||||
|
|
||||||
def _background_update_progress_txn(self, txn, update_name, progress):
|
def _background_update_progress_txn(self, txn, update_name, progress):
|
||||||
"""Update the progress of a background update
|
"""Update the progress of a background update
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
import collections
|
import collections
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
|
from abc import abstractmethod
|
||||||
from typing import Optional, Tuple
|
from typing import Optional, Tuple
|
||||||
|
|
||||||
from six import integer_types
|
from six import integer_types
|
||||||
|
@ -367,6 +368,8 @@ class RoomWorkerStore(SQLBaseStore):
|
||||||
|
|
||||||
|
|
||||||
class RoomBackgroundUpdateStore(SQLBaseStore):
|
class RoomBackgroundUpdateStore(SQLBaseStore):
|
||||||
|
REMOVE_TOMESTONED_ROOMS_BG_UPDATE = "remove_tombstoned_rooms_from_directory"
|
||||||
|
|
||||||
def __init__(self, database: Database, db_conn, hs):
|
def __init__(self, database: Database, db_conn, hs):
|
||||||
super(RoomBackgroundUpdateStore, self).__init__(database, db_conn, hs)
|
super(RoomBackgroundUpdateStore, self).__init__(database, db_conn, hs)
|
||||||
|
|
||||||
|
@ -376,6 +379,11 @@ class RoomBackgroundUpdateStore(SQLBaseStore):
|
||||||
"insert_room_retention", self._background_insert_retention,
|
"insert_room_retention", self._background_insert_retention,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.db.updates.register_background_update_handler(
|
||||||
|
self.REMOVE_TOMESTONED_ROOMS_BG_UPDATE,
|
||||||
|
self._remove_tombstoned_rooms_from_directory,
|
||||||
|
)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def _background_insert_retention(self, progress, batch_size):
|
def _background_insert_retention(self, progress, batch_size):
|
||||||
"""Retrieves a list of all rooms within a range and inserts an entry for each of
|
"""Retrieves a list of all rooms within a range and inserts an entry for each of
|
||||||
|
@ -444,6 +452,62 @@ class RoomBackgroundUpdateStore(SQLBaseStore):
|
||||||
|
|
||||||
defer.returnValue(batch_size)
|
defer.returnValue(batch_size)
|
||||||
|
|
||||||
|
async def _remove_tombstoned_rooms_from_directory(
|
||||||
|
self, progress, batch_size
|
||||||
|
) -> int:
|
||||||
|
"""Removes any rooms with tombstone events from the room directory
|
||||||
|
|
||||||
|
Nowadays this is handled by the room upgrade handler, but we may have some
|
||||||
|
that got left behind
|
||||||
|
"""
|
||||||
|
|
||||||
|
last_room = progress.get("room_id", "")
|
||||||
|
|
||||||
|
def _get_rooms(txn):
|
||||||
|
txn.execute(
|
||||||
|
"""
|
||||||
|
SELECT room_id
|
||||||
|
FROM rooms r
|
||||||
|
INNER JOIN current_state_events cse USING (room_id)
|
||||||
|
WHERE room_id > ? AND r.is_public
|
||||||
|
AND cse.type = '%s' AND cse.state_key = ''
|
||||||
|
ORDER BY room_id ASC
|
||||||
|
LIMIT ?;
|
||||||
|
"""
|
||||||
|
% EventTypes.Tombstone,
|
||||||
|
(last_room, batch_size),
|
||||||
|
)
|
||||||
|
|
||||||
|
return [row[0] for row in txn]
|
||||||
|
|
||||||
|
rooms = await self.db.runInteraction(
|
||||||
|
"get_tombstoned_directory_rooms", _get_rooms
|
||||||
|
)
|
||||||
|
|
||||||
|
if not rooms:
|
||||||
|
await self.db.updates._end_background_update(
|
||||||
|
self.REMOVE_TOMESTONED_ROOMS_BG_UPDATE
|
||||||
|
)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
for room_id in rooms:
|
||||||
|
logger.info("Removing tombstoned room %s from the directory", room_id)
|
||||||
|
await self.set_room_is_public(room_id, False)
|
||||||
|
|
||||||
|
await self.db.updates._background_update_progress(
|
||||||
|
self.REMOVE_TOMESTONED_ROOMS_BG_UPDATE, {"room_id": rooms[-1]}
|
||||||
|
)
|
||||||
|
|
||||||
|
return len(rooms)
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def set_room_is_public(self, room_id, is_public):
|
||||||
|
# this will need to be implemented if a background update is performed with
|
||||||
|
# existing (tombstoned, public) rooms in the database.
|
||||||
|
#
|
||||||
|
# It's overridden by RoomStore for the synapse master.
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
class RoomStore(RoomBackgroundUpdateStore, RoomWorkerStore, SearchStore):
|
class RoomStore(RoomBackgroundUpdateStore, RoomWorkerStore, SearchStore):
|
||||||
def __init__(self, database: Database, db_conn, hs):
|
def __init__(self, database: Database, db_conn, hs):
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
/* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
-- Now that #6232 is a thing, we can remove old rooms from the directory.
|
||||||
|
INSERT INTO background_updates (update_name, progress_json) VALUES
|
||||||
|
('remove_tombstoned_rooms_from_directory', '{}');
|
Loading…
Reference in New Issue