From 06fd08b4ed91410ad9a4ec829d6bae1a3de5780e Mon Sep 17 00:00:00 2001 From: Lee Hannigan <29015211+LeeroyHannigan@users.noreply.github.com> Date: Tue, 10 Nov 2026 14:14:57 +0000 Subject: [PATCH] test(storage-postgres): wait for the vector index hold release update_table_creates_a_vector_index_and_backfills_what_is_already_there polls the catalog until the new vector index is ACTIVE, then counts the index holds once. mark_active commits the ACTIVE flip on the catalog first and releases the hold afterwards, in a second statement on the data database. A count taken between the two statements finds the hold, and the test fails. The run-postgres-storage-tests job of #927 failed this way on 10 Nov. The test now polls the hold count for up to 10 s, as it polls the status. The order in mark_active stays as it is. A hold released before the flip would let the worker apply a write to an unpublished index. --- .../storage-postgres/tests/vector_control_plane.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/crates/storage-postgres/tests/vector_control_plane.rs b/crates/storage-postgres/tests/vector_control_plane.rs index ae14e0329..794708312 100644 --- a/crates/storage-postgres/tests/vector_control_plane.rs +++ b/crates/storage-postgres/tests/vector_control_plane.rs @@ -955,12 +955,21 @@ async fn update_table_creates_a_vector_index_and_backfills_what_is_already_there 1, "the pre-existing item must be backfilled" ); - let holds: i64 = - sqlx::query_scalar("SELECT COUNT(*) FROM vector_index_holds WHERE table_id = $1") + // `mark_active` commits the ACTIVE flip on the catalog first and releases the hold + // afterwards, in a second statement on the data database. The poll above can see + // ACTIVE between the two, so wait for the release instead of reading the count once. + let mut holds: i64 = -1; + for _ in 0..100 { + holds = sqlx::query_scalar("SELECT COUNT(*) FROM vector_index_holds WHERE table_id = $1") .bind(&id) .fetch_one(s.engine.data_pool()) .await .expect("count the holds"); + if holds == 0 { + break; + } + tokio::time::sleep(std::time::Duration::from_millis(100)).await; + } assert_eq!(holds, 0, "the hold must be released after the ACTIVE flip"); let (backfilling, owner): (Option, Option) = sqlx::query_as("SELECT backfilling, build_owner FROM vector_indexes WHERE table_id = $1")