diff --git a/crates/buzz-db/src/runtime/tests/reader_pool_postgres_tests.rs b/crates/buzz-db/src/runtime/tests/reader_pool_postgres_tests.rs index f53fed7c76..a4aaf473c9 100644 --- a/crates/buzz-db/src/runtime/tests/reader_pool_postgres_tests.rs +++ b/crates/buzz-db/src/runtime/tests/reader_pool_postgres_tests.rs @@ -144,10 +144,11 @@ async fn reader_boot_ping_warms_pool_to_max_in_background() { /// At the production acquire budget, a reader that admits only some dials /// ends the warm pass bounded and partial, with no re-dialing. The pool is /// built by the production constructor, so each warm acquire, dial -/// included, gets only [`Db::READER_ACQUIRE_TIMEOUT`]. The proxy relays the -/// first 3 sessions and stalls every later dial mid-handshake: the first -/// wave of 5 holds 3, the second wave's 5 dials all miss, and that wave's -/// lack of progress ends the pass after exactly 10 dials. +/// included, gets only [`Db::READER_ACQUIRE_TIMEOUT`]. Follow production boot +/// order: first fill the idle floor, then stall every new dial mid-handshake. +/// The first wave holds the 3 idle connections and misses 2 dials; the next +/// wave misses all 5 and stops. Cold authentication is outside the measured +/// warm pass, so debug-build SCRAM throughput cannot change that accounting. #[tokio::test] #[ignore = "requires Postgres"] async fn reader_warm_at_production_budget_ends_partial_when_dials_stall() { @@ -156,7 +157,6 @@ async fn reader_warm_at_production_budget_ends_partial_when_dials_stall() { let writer_options = writer.connect_options(); let (host, port) = (writer_options.get_host(), writer_options.get_port()); let proxy = crate::test_support::PausingProxy::spawn(host.to_owned(), port).await; - proxy.stall_from(3); let scratch_url = scratch.url(); let proxied_url = scratch_url.replacen( &format!("{host}:{port}"), @@ -169,6 +169,18 @@ async fn reader_warm_at_production_budget_ends_partial_when_dials_stall() { ); let read_pool = Db::connect_read_pool(&DbConfig::default(), &proxied_url, max) .expect("production reader pool"); + let floor = Db::reader_min_connections(max); + assert_eq!( + floor, 3, + "fixture needs three established reader connections" + ); + assert!( + Db::read_pool_boot_ping_once(read_pool.clone(), Default::default()).await, + "reader reachable at boot" + ); + await_idle_floor(&read_pool, floor).await; + let seeded = proxy.sessions(); + proxy.stall_from(seeded); let started = Instant::now(); let report = Db::warm_read_pool(&read_pool).await; @@ -176,17 +188,21 @@ async fn reader_warm_at_production_budget_ends_partial_when_dials_stall() { assert_eq!( (report.target, report.held, report.failed), - (max, 3, 7), + (max, floor, 7), "one partial wave, then one wave that opens nothing" ); - assert_eq!(proxy.sessions(), 10, "the pass must stop dialing"); + assert_eq!(proxy.sessions() - seeded, 7, "the pass must stop dialing"); assert!( elapsed < Duration::from_secs(2), "two waves at the production budget must end promptly: {elapsed:?}" ); - await_idle_floor(&read_pool, 3).await; + await_idle_floor(&read_pool, floor).await; tokio::time::sleep(Duration::from_millis(300)).await; - assert_eq!(proxy.sessions(), 10, "nothing re-dials after the pass"); + assert_eq!( + proxy.sessions() - seeded, + 7, + "nothing re-dials after the pass" + ); read_pool.close().await; }