diff --git a/crates/buzz-db/src/runtime/replica_fence.rs b/crates/buzz-db/src/runtime/replica_fence.rs index f1fb75bf75..8117a2690c 100644 --- a/crates/buzz-db/src/runtime/replica_fence.rs +++ b/crates/buzz-db/src/runtime/replica_fence.rs @@ -52,9 +52,9 @@ //! mismatch, or an observed token below every retained entry all route the //! request back to the writer — degraded capacity, never holes. //! -//! Raw SQL without the armed GUC and `session_replication_role = replica` -//! restores bypass the supported app writers. These operational bypasses are -//! outside the proof and require holding the fence closed; see `migrations/0021`. +//! Raw SQL and `session_replication_role = replica` restores bypass the +//! application floor check. These operational bypasses are outside the proof +//! and require holding the fence closed. use std::collections::VecDeque; use std::sync::{Arc, Mutex}; diff --git a/crates/buzz-db/src/runtime/tests/floor_retirement.rs b/crates/buzz-db/src/runtime/tests/floor_retirement.rs index 6fe582a23e..fbf3e20c5e 100644 --- a/crates/buzz-db/src/runtime/tests/floor_retirement.rs +++ b/crates/buzz-db/src/runtime/tests/floor_retirement.rs @@ -96,28 +96,20 @@ async fn migration_schema_floor_retirement_cleans_child_copies_idempotently() { #[tokio::test] #[ignore = "requires Postgres"] -async fn floor_retirement_desired_and_migrated_catalogs_match() { +async fn floor_retirement_desired_state_has_no_floor_objects() { // The nextest wrapper bootstraps this database through real pgschema apply - // and reconciliation. Check the retired floor catalog against the real - // migration boot path; unrelated trigger/FK preservation is checked above. + // and reconciliation; desired-state/migration parity is checked by + // `admin_schema_parity_between_desired_state_and_migrations`. let pool = PgPool::connect(&crate::test_support::database_url()) .await .expect("connect desired-state database"); assert_eq!(floor_objects(&pool).await, (0, 0)); - sqlx::raw_sql("DROP SCHEMA public CASCADE; CREATE SCHEMA public;") - .execute(&pool) - .await - .expect("reset isolated database for migration boot"); - crate::migration::run_migrations(&pool) - .await - .expect("boot migration schema"); - assert_eq!(floor_objects(&pool).await, (0, 0)); pool.close().await; } #[tokio::test] #[ignore = "requires Postgres"] -async fn floor_retirement_writer_and_probe_accept_legacy_and_retired_schema() { +async fn floor_retirement_writer_and_probe_run_on_retired_schema() { let url = crate::test_support::database_url(); let db = Db::new(&DbConfig { database_url: url.clone(), @@ -140,18 +132,6 @@ async fn floor_retirement_writer_and_probe_accept_legacy_and_retired_schema() { .await .expect("retired schema still supports the ordered heartbeat"); - // This binary can also run before migration, without changing legacy SQL. - sqlx::raw_sql(include_str!( - "../../../../../migrations/0021_created_at_fence_floor.sql" - )) - .execute(&db.pool) - .await - .expect("restore actual legacy guard"); - assert!(floor_objects(&db.pool).await.0 > 1); - assert!(db.spawn_fence_probe()); - crate::replica_fence::probe_once(&db.pool, db.fence()) - .await - .expect("legacy schema still supports ordered heartbeat"); db.pool.close().await; db.read_pool .as_ref() diff --git a/crates/buzz-db/tests/observability_source.rs b/crates/buzz-db/tests/observability_source.rs index 1aab895598..3e176621aa 100644 --- a/crates/buzz-db/tests/observability_source.rs +++ b/crates/buzz-db/tests/observability_source.rs @@ -2169,7 +2169,7 @@ fn event_floor_guard_uses_the_database_statement_clock_and_shared_floor() { ); assert!( guard.contains(".bind(CREATED_AT_FLOOR_SECS as f64)"), - "app check, GUC and fence wall must share the same floor constant" + "app check and fence wall must share the same floor constant" ); } diff --git a/migrations/0062_retire_created_at_floor.sql b/migrations/0062_retire_created_at_floor.sql index fac3f74364..057171e975 100644 --- a/migrations/0062_retire_created_at_floor.sql +++ b/migrations/0062_retire_created_at_floor.sql @@ -5,6 +5,9 @@ SET LOCAL lock_timeout = '5s'; -- and hold the replica breaker closed through this drop until replay catches -- up. Old pods that already started do not recheck the guard on each probe. -- Keep the 960-second application floor and the ordered heartbeat handshake. +-- DROP TRIGGER takes ACCESS EXCLUSIVE on events and every partition, so it +-- can stall events reads/writes for up to lock_timeout. Run off-peak; a lock +-- timeout aborts the whole migration and is safe to retry. -- No other trigger, function, FK, or tenant fence is retired here. DROP TRIGGER IF EXISTS events_created_at_floor ON events;