test(db): warm the reader floor before stalling new dials

Follow production boot order so the partial warm-pass assertion does not depend on three cold debug-build authentications completing in 150ms. Keep the production budget and exact stalled-dial accounting.

Co-authored-by: Honor <e0bf479eeebe47dde1e35705212a4df70616a7bc834d907ddfb18cf0405f8b1b@seiler-test.communities.public.builderlabstaging.xyz>

Co-authored-by: McKeon <f87db83c2e79e370e2349ac850d9f04afe307b90f25a2830f50e825ba75e3cc5@seiler-test.communities.public.builderlabstaging.xyz>
Signed-off-by: Brad Seiler <seiler@squareup.com>
This commit is contained in:
Brad Seiler
2026-11-04 17:09:45 -05:00
parent 393d144b5c
commit 7c29360d7d

View File

@@ -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;
}