test(search): serialize pgcrypto install to fix parallel-setup race

fts_integration.rs setup() applies migration 0001, which contains
CREATE EXTENSION IF NOT EXISTS pgcrypto.  pg_extension is database-
global with a unique index on extname; IF NOT EXISTS is a check-then-
insert, not an atomic upsert.  When 18 tests run in parallel, the first
wave all see the extension as absent, all attempt the insert, and all
but one hit SQLSTATE 23505 (duplicate key on pg_extension_name_index).

Fix: take a session-level pg_advisory_lock on the admin connection
before the extension create, release it after.  This serializes the
install across all parallel test workers so exactly one does the real
CREATE; the rest treat it as a no-op on lock acquisition.  The advisory
lock is released automatically when the session ends.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
This commit is contained in:
npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7
2026-07-14 00:21:25 -04:00
committed by Will Pfleger
co-authored by Will Pfleger
parent 6dda6fd7c3
commit 6eb6ab1a1e
@@ -38,6 +38,31 @@ async fn setup() -> (PgPool, String) {
.connect(&url)
.await
.expect("connect");
// Serialize the pgcrypto extension install across all parallel test workers.
//
// `CREATE EXTENSION IF NOT EXISTS pgcrypto` targets `pg_extension`, which is
// database-global with a unique index on `extname`. PostgreSQL's IF NOT EXISTS
// is a check-then-insert, not an atomic upsert: when many test workers run
// concurrently they all see the extension as absent, all attempt the insert,
// and all but one hit SQLSTATE 23505 (unique violation). A session-level
// advisory lock (arbitrary but stable key) serializes the install so that
// exactly one worker does the real CREATE; the rest treat it as a no-op when
// they enter the lock. The lock is released automatically when the session
// ends, so there is no risk of wedging subsequent runs.
sqlx::query("SELECT pg_advisory_lock(3723742987654321)")
.execute(&admin_pool)
.await
.expect("acquire pgcrypto advisory lock");
sqlx::query("CREATE EXTENSION IF NOT EXISTS pgcrypto")
.execute(&admin_pool)
.await
.expect("install pgcrypto extension");
sqlx::query("SELECT pg_advisory_unlock(3723742987654321)")
.execute(&admin_pool)
.await
.expect("release pgcrypto advisory lock");
let create_sql = format!("CREATE SCHEMA \"{schema}\"");
sqlx::query(sqlx::AssertSqlSafe(create_sql))
.execute(&admin_pool)