Skip to content

Commit

Permalink
Sanity-check database before running upgrades (matrix-org#6982)
Browse files Browse the repository at this point in the history
Some of the database deltas rely on `config.server_name` being set correctly,
so we should check that it is before running the deltas.

Fixes matrix-org#6870.
  • Loading branch information
richvdh authored and phil-flex committed Mar 27, 2020
1 parent 96b1910 commit 61ac743
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 17 deletions.
1 change: 1 addition & 0 deletions changelog.d/6982.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Check that server_name is correctly set before running database updates.
34 changes: 19 additions & 15 deletions synapse/storage/data_stores/main/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import time

from synapse.api.constants import PresenceState
from synapse.config.homeserver import HomeServerConfig
from synapse.storage.database import Database
from synapse.storage.engines import PostgresEngine
from synapse.storage.util.id_generators import (
Expand Down Expand Up @@ -117,16 +118,6 @@ def __init__(self, database: Database, db_conn, hs):
self._clock = hs.get_clock()
self.database_engine = database.engine

all_users_native = are_all_users_on_domain(
db_conn.cursor(), database.engine, hs.hostname
)
if not all_users_native:
raise Exception(
"Found users in database not native to %s!\n"
"You cannot changed a synapse server_name after it's been configured"
% (hs.hostname,)
)

self._stream_id_gen = StreamIdGenerator(
db_conn,
"events",
Expand Down Expand Up @@ -567,13 +558,26 @@ def search_users(self, term):
)


def are_all_users_on_domain(txn, database_engine, domain):
def check_database_before_upgrade(cur, database_engine, config: HomeServerConfig):
"""Called before upgrading an existing database to check that it is broadly sane
compared with the configuration.
"""
domain = config.server_name

sql = database_engine.convert_param_style(
"SELECT COUNT(*) FROM users WHERE name NOT LIKE ?"
)
pat = "%:" + domain
txn.execute(sql, (pat,))
num_not_matching = txn.fetchall()[0][0]
cur.execute(sql, (pat,))
num_not_matching = cur.fetchall()[0][0]
if num_not_matching == 0:
return True
return False
return

raise Exception(
"Found users in database not native to %s!\n"
"You cannot changed a synapse server_name after it's been configured"
% (domain,)
)


__all__ = ["DataStore", "check_database_before_upgrade"]
15 changes: 13 additions & 2 deletions synapse/storage/prepare_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,20 +278,31 @@ def _upgrade_existing_database(
the current_version wasn't generated by applying those delta files.
database_engine (DatabaseEngine)
config (synapse.config.homeserver.HomeServerConfig|None):
application config, or None if we are connecting to an existing
database which we expect to be configured already
None if we are initialising a blank database, otherwise the application
config
data_stores (list[str]): The names of the data stores to instantiate
on the given database.
is_empty (bool): Is this a blank database? I.e. do we need to run the
upgrade portions of the delta scripts.
"""
if is_empty:
assert not applied_delta_files
else:
assert config

if current_version > SCHEMA_VERSION:
raise ValueError(
"Cannot use this database as it is too "
+ "new for the server to understand"
)

# some of the deltas assume that config.server_name is set correctly, so now
# is a good time to run the sanity check.
if not is_empty and "main" in data_stores:
from synapse.storage.data_stores.main import check_database_before_upgrade

check_database_before_upgrade(cur, database_engine, config)

start_ver = current_version
if not upgraded:
start_ver += 1
Expand Down

0 comments on commit 61ac743

Please sign in to comment.