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

Speed up SQLite unit test CI #15334

Merged
merged 7 commits into from
Mar 30, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Comments
  • Loading branch information
erikjohnston committed Mar 30, 2023
commit 6799a42cc83034562be009f731e43c41934f5f40
4 changes: 4 additions & 0 deletions synapse/storage/engines/sqlite.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ def __init__(self, database_config: Mapping[str, Any]):
":memory:",
)

# A connection to a database that has already been prepared, to use as a
# base for an in-memory connection. This is used during unit tests to
# speed up setting up the DB.
self._prepped_conn: Optional[sqlite3.Connection] = database_config.get(
"_TEST_PREPPED_CONN"
)
Expand Down Expand Up @@ -86,6 +89,7 @@ def on_new_connection(self, db_conn: "LoggingDatabaseConnection") -> None:

if self._is_in_memory:
if self._prepped_conn is not None:
# Initialise the new DB from the pre-prepared DB.
assert isinstance(db_conn.conn, sqlite3.Connection)
self._prepped_conn.backup(db_conn.conn)
else:
Expand Down
17 changes: 11 additions & 6 deletions tests/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,9 @@
# the type of thing that can be passed into `make_request` in the headers list
CustomHeaderType = Tuple[Union[str, bytes], Union[str, bytes]]

PREPPED_DB_CONN: Optional[LoggingDatabaseConnection] = None
# A pre-prepared SQLite DB that is used as a template when creating new SQLite
# DB each test run. This dramatically speeds up test set up when using SQLite.
PREPPED_SQlITE_DB_CONN: Optional[LoggingDatabaseConnection] = None


class TimedOutException(Exception):
Expand Down Expand Up @@ -904,18 +906,21 @@ def setup_test_homeserver(
"args": {"database": test_db_location, "cp_min": 1, "cp_max": 1},
}

global PREPPED_DB_CONN
if PREPPED_DB_CONN is None:
# Check if we have set up a DB that we can use as a template.
global PREPPED_SQlITE_DB_CONN
erikjohnston marked this conversation as resolved.
Show resolved Hide resolved
if PREPPED_SQlITE_DB_CONN is None:
temp_engine = create_engine(database_config)
PREPPED_DB_CONN = LoggingDatabaseConnection(
PREPPED_SQlITE_DB_CONN = LoggingDatabaseConnection(
sqlite3.connect(":memory:"), temp_engine, "PREPPED_CONN"
)

database = DatabaseConnectionConfig("master", database_config)
config.database.databases = [database]
prepare_database(PREPPED_DB_CONN, create_engine(database_config), config)
prepare_database(
PREPPED_SQlITE_DB_CONN, create_engine(database_config), config
)

database_config["_TEST_PREPPED_CONN"] = PREPPED_DB_CONN
database_config["_TEST_PREPPED_CONN"] = PREPPED_SQlITE_DB_CONN

if "db_txn_limit" in kwargs:
database_config["txn_limit"] = kwargs["db_txn_limit"]
Expand Down
15 changes: 13 additions & 2 deletions tests/unittest.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,22 @@ def tearDown(orig: Callable[[], R]) -> R:

return orig()

# We want to force a GC to workaround problems with deferreds leaking
# logcontexts when they are GCed (see the logcontext docs).
#
# The easiest way to do this would be to do a full GC after each test
# run, but that is very expensive. Instead, we disable GC for the
# duration of the test so that we only need to run a gen-0 GC, which is
# a lot quicker.

@around(self)
def setUp(orig: Callable[[], R]) -> R:
gc.disable()
return orig()

@around(self)
def tearDown(orig: Callable[[], R]) -> R:
ret = orig()
# force a GC to workaround problems with deferreds leaking logcontexts when
# they are GCed (see the logcontext docs)
gc.collect(0)
set_current_context(SENTINEL_CONTEXT)

Expand Down