From 403855d7884971b4103ba094e3d24ba28bbf093a Mon Sep 17 00:00:00 2001 From: Logan Johnson Date: Tue, 27 Oct 2026 16:55:51 -0400 Subject: [PATCH] test(relay): give group-state Postgres tests a normal acquire timeout (#8564) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 ## Summary The relay's PostgreSQL CI job sometimes fails in the channel group-state tests with `ensure community: Sqlx(PoolTimedOut)`. The tests themselves are fine. They connect to the test database through a test helper that waits only 100 ms for a connection, and on a busy CI runner the first connection can take longer than that. One example is `group_state_events_carry_type_then_creator` in [this #8522 run](https://github.com/block/buzz/actions/runs/40013074144/job/120623293420): it failed after 0.57 s, while its other 1110 tests passed. This PR gives these tests a pool with sqlx's normal acquire timeout. No product code changes. ## Details - `test_state_with_database_url` keeps its 100 ms timeout on purpose. Its other callers point at a closed port (`127.0.0.1:1`) to test fail-closed paths, and the short timeout makes them fail fast. - `group_state_postgres_tests::state()` is the only caller that passes it the real test database. It now builds a normal lazy pool and passes it to `test_state_with_database_pool`. The same `state()` also serves `create_with_members_postgres_tests`, `edit_metadata_postgres_tests`, and `system_channel_postgres_tests`. ### Related issue N/A. I searched open PRs for `PoolTimedOut` and `acquire_timeout` and found none for this. ### Testing To reproduce a slow first connection, I ran the tests through a local TCP proxy that waits 250 ms before it connects to Postgres: - Before this change: `group_state_postgres_tests` had 13 of 14 tests fail with `PoolTimedOut`. - After this change: all 14 pass. `create_with_members_postgres_tests` (3), `edit_metadata_postgres_tests` (7), and `system_channel_postgres_tests` (9) also pass through the same proxy. - Without the proxy, all 14 pass before and after. - `cargo clippy -p buzz-relay --all-targets -D warnings` and `just test-unit` pass. --------- Signed-off-by: Logan Johnson Co-authored-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz> Co-authored-by: Claude Opus 5.5 --- .../handlers/group_state_postgres_tests.rs | 10 +++++++++- crates/buzz-relay/src/state.rs | 19 +++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/crates/buzz-relay/src/handlers/group_state_postgres_tests.rs b/crates/buzz-relay/src/handlers/group_state_postgres_tests.rs index 89c38355ea..f0586181d9 100644 --- a/crates/buzz-relay/src/handlers/group_state_postgres_tests.rs +++ b/crates/buzz-relay/src/handlers/group_state_postgres_tests.rs @@ -12,8 +12,16 @@ use crate::handlers::ingest::{ingest_event, HttpAuthMethod, IngestAuth}; use crate::state::AppState; use buzz_auth::Scope; +/// Test state on the shared test database. The pool keeps sqlx's default +/// acquire timeout: `test_state_with_database_url` waits only 100 ms so +/// closed-port tests fail fast, and a first connect to a busy CI database can +/// take longer than that (`PoolTimedOut`). pub(crate) async fn state() -> Arc { - crate::state::tests::test_state_with_database_url(&crate::test_support::database_url()).await + crate::state::tests::test_state_with_database_url_and_pool_options( + &crate::test_support::database_url(), + sqlx::postgres::PgPoolOptions::new(), + ) + .await } pub(crate) async fn community(state: &AppState, label: &str) -> TenantContext { diff --git a/crates/buzz-relay/src/state.rs b/crates/buzz-relay/src/state.rs index b4bdd62108..369a57a801 100644 --- a/crates/buzz-relay/src/state.rs +++ b/crates/buzz-relay/src/state.rs @@ -2970,15 +2970,30 @@ pub(crate) mod tests { /// The same test state with an explicit database target. This lets handler /// tests deterministically exercise fail-closed database seams without /// depending on whether a developer has the normal test database running. + /// Its pool waits only 100 ms for a connection, so closed-port targets + /// fail fast. pub(crate) async fn test_state_with_database_url(database_url: &str) -> Arc { + test_state_with_database_url_and_pool_options( + database_url, + sqlx::postgres::PgPoolOptions::new() + .acquire_timeout(std::time::Duration::from_millis(100)), + ) + .await + } + + /// Test state whose config and writer pool both target `database_url`, + /// with the caller's pool options. + pub(crate) async fn test_state_with_database_url_and_pool_options( + database_url: &str, + options: sqlx::postgres::PgPoolOptions, + ) -> Arc { // Fix 5: use Config::for_test() which holds NIP_FI_ENV_LOCK internally. [FI-TRACE-ENV-RACE] let mut config = crate::config::Config::for_test(); config.require_relay_membership = false; config.redis_url = "redis://127.0.0.1:1".to_string(); config.database_url = database_url.to_owned(); config.read_database_url = None; - let pool = sqlx::postgres::PgPoolOptions::new() - .acquire_timeout(std::time::Duration::from_millis(100)) + let pool = options .connect_lazy(&config.database_url) .expect("lazy pg pool"); build_test_state(config, pool).await