Skip to content

Use PostgreSQL template database for faster test resets#1040

Open
rowanseymour wants to merge 3 commits intomainfrom
speed-up-tests-template-db
Open

Use PostgreSQL template database for faster test resets#1040
rowanseymour wants to merge 3 commits intomainfrom
speed-up-tests-template-db

Conversation

@rowanseymour
Copy link
Copy Markdown
Member

Summary

resetDB (used by Reset(t, rt, ResetAll|ResetDB)) now drops mailroom_test and recreates it from a mailroom_test_tpl template database instead of running pg_restore on every reset. PostgreSQL clones a template at the file system level, which is dramatically faster than parsing the dump and reinserting/reindexing.

The template is built once on first run (or when missing), in Runtime() startup, by cloning the freshly-loaded mailroom_test. After regenerating the dump, drop both mailroom_test and mailroom_test_tpl so the next test run rebuilds them.

Local timings (devcontainer, go test -count=1 -p=1 ./...):

main this PR
full suite ~2m53s ~1m53s
core/models 25.6s 5.6s
core/runner/handlers 29.7s 4.0s

No test files were touched. The same set of pre-existing flaky tests (TestMsgReceivedTask, TestOptinRequested in isolation, TestBroadcastsFromEvents in some orderings) fail on both branches identically.

Test plan

  • go test -count=1 -p=1 ./core/models/ passes
  • go test -count=1 -p=1 ./core/runner/handlers/ passes
  • go test -count=1 -p=1 ./web/... passes
  • go test -count=1 -p=1 ./... produces the same set of failures as main

resetDB now drops mailroom_test and recreates it from a mailroom_test_tpl
template database (built once on startup) instead of running pg_restore
on every reset. PostgreSQL clones a template at the file-system level,
which is dramatically faster than parsing and reinserting the dump.

Locally, the full ./... suite goes from ~2m53s to ~1m53s (~35% faster);
core/models alone goes from 25.6s to 5.6s.

After regenerating the dump, drop both mailroom_test and mailroom_test_tpl
so the next test run rebuilds them.
Copilot AI review requested due to automatic review settings April 7, 2026 23:18
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR speeds up Go test database resets by switching testsuite.resetDB from pg_restore-based resets to cloning a PostgreSQL template database, reducing suite runtime by avoiding repeated restore/reindex work.

Changes:

  • Build a mailroom_test_tpl template DB on first test runtime startup (when missing).
  • Update resetDB to drop mailroom_test and recreate it via CREATE DATABASE ... TEMPLATE mailroom_test_tpl.
  • Add helper functions for admin DB access and for reopening the sqlx pool after cloning.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread testsuite/runtime.go
Comment on lines +188 to +191
var exists bool
err := admin.QueryRow(`SELECT EXISTS(SELECT 1 FROM pg_database WHERE datname = $1)`, templateDBName).Scan(&exists)
require.NoError(t, err)
return exists
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

templateDBExists only checks for the presence of a database named mailroom_test_tpl, but doesn’t verify it’s correctly configured as a safe clone source (e.g. datistemplate and/or disallowing connections). If the DB exists but is misconfigured or was modified, resets will silently clone bad state. Consider querying pg_database for datistemplate/datallowconn (or equivalent) and recreating the template when it’s not in the expected state.

Copilot uses AI. Check for mistakes.
Comment thread testsuite/runtime.go Outdated
CI saw `CREATE DATABASE ... TEMPLATE` fail with "source database is being
accessed by other users" on the first run when no template existed yet.
Closing rt.DB isn't always sufficient — earlier setup paths can leak pools
and lib/pq may leave idle connections behind. Terminate any other backends
to mailroom_test before cloning.
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Apr 8, 2026

Codecov Report

❌ Patch coverage is 0% with 47 lines in your changes missing coverage. Please review.
✅ Project coverage is 52.26%. Comparing base (f4c2627) to head (af1d0ca).

Files with missing lines Patch % Lines
testsuite/runtime.go 0.00% 47 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1040      +/-   ##
==========================================
- Coverage   52.45%   52.26%   -0.19%     
==========================================
  Files         275      275              
  Lines       12682    12727      +45     
==========================================
  Hits         6652     6652              
- Misses       5188     5233      +45     
  Partials      842      842              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

PR feedback: datistemplate=TRUE alone doesn't block connections, it only
gates non-superuser template usage. Also set datallowconn=false so the
template really can't be accidentally connected to and modified.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants