From 7c1aa0b29b909a770f46ed329f4ba09eec416666 Mon Sep 17 00:00:00 2001 From: Xiaoyang Han Date: Thu, 8 Oct 2026 03:54:16 +0800 Subject: [PATCH] test(mst2): observe actual retention waits and drain deferred fixture events The persisted META concurrency oracle now observes the actual advisory lock tuple in its current PostgreSQL database and schema, without relying on application_name from a statistics snapshot. It still requires a real waiting competitor, unfinished reader and competitor, both exact route bytes, root/directory counts, release or GC behavior, successful post-read collection and rejection of the old context. A competitor that returns early reports its actual result and release/GC case instead of being hidden by a wait timeout. The source of the earlier timeout has not yet been established by a new native run. The bound-current corruption fixture keeps its active, deferrable, initially deferred protection trigger, executes its queued check explicitly before ALTER TABLE, restores deferred mode, and reenables the original mutation guard before commit. All six original damage/repair cases, exact HTTP errors, recovered canonical bytes and complete trigger-mode checks remain. This addresses the observed PostgreSQL pending-trigger-events error without disabling completeness protection. Production code and guards are unchanged. Local nightly formatting, diff and locked offline no-dependency metadata pass; new native results and all performance measurements remain pending. --- .../snapshot_persisted_metadata_tests.rs | 40 ++++++++++++++++--- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/src/api/router/snapshot_persisted_metadata_tests.rs b/src/api/router/snapshot_persisted_metadata_tests.rs index 028f7d35..f66d58da 100644 --- a/src/api/router/snapshot_persisted_metadata_tests.rs +++ b/src/api/router/snapshot_persisted_metadata_tests.rs @@ -377,9 +377,10 @@ async fn wait_retention_waiter(txn: &sea_orm::DatabaseTransaction) { .unwrap(); if scalar( txn, - "SELECT count(*) FROM pg_locks l JOIN pg_stat_activity a ON a.pid=l.pid - WHERE l.locktype='advisory' AND NOT l.granted AND a.datname=current_database() - AND a.application_name=current_schema() AND l.classid=1296717362::oid + "SELECT count(*) FROM pg_locks l + WHERE l.locktype='advisory' AND NOT l.granted + AND l.database=(SELECT oid FROM pg_database WHERE datname=current_database()) + AND l.pid<>pg_backend_pid() AND l.classid=1296717362::oid AND l.objid=hashtext(current_schema())::oid AND l.objsubid=2", ) .await @@ -664,7 +665,7 @@ async fn mst2_persisted_meta_reader_holds_protection_until_all_route_bytes_are_o .await .unwrap(); let root = format!("page:{}", context.built.metadata_root); - let competing = { + let mut competing = { let state = fixture.state.clone(); let lease = fixture.lease.clone(); let root = root.clone(); @@ -692,7 +693,12 @@ async fn mst2_persisted_meta_reader_holds_protection_until_all_route_bytes_are_o .begin() .await .unwrap(); - wait_retention_waiter(&observer).await; + tokio::select! { + () = wait_retention_waiter(&observer) => {}, + outcome = &mut competing => { + panic!("retention competitor completed before waiting: release_lease={release_lease}, outcome={outcome:?}"); + }, + } assert!(!reading.is_finished()); assert!(!competing.is_finished()); resume.wait().await; @@ -834,6 +840,30 @@ async fn fault_binding(fixture: &Fixture, id: [u8; 32], case: usize, restore: bo .rows_affected(), 1 ); + if case == 1 { + let protection = txn + .query_one_raw(Statement::from_string( + DbBackend::Postgres, + "SELECT t.tgenabled::text AS mode,t.tgdeferrable AS deferrable,t.tginitdeferred AS deferred + FROM pg_trigger t WHERE t.tgrelid='mst2_metadata_current'::regclass + AND t.tgname='mst2_metadata_current_protected' AND NOT t.tgisinternal", + )) + .await + .unwrap() + .unwrap(); + assert!(matches!( + protection.try_get::("", "mode").unwrap().as_str(), + "O" | "A" + )); + assert!(protection.try_get::("", "deferrable").unwrap()); + assert!(protection.try_get::("", "deferred").unwrap()); + txn.execute_unprepared("SET CONSTRAINTS mst2_metadata_current_protected IMMEDIATE") + .await + .unwrap(); + txn.execute_unprepared("SET CONSTRAINTS mst2_metadata_current_protected DEFERRED") + .await + .unwrap(); + } txn.execute_unprepared(&format!("ALTER TABLE {table} ENABLE TRIGGER {guard}")) .await .unwrap();