From e54ce0b2da62ac71e3b2a5212f32e82b07bf39a5 Mon Sep 17 00:00:00 2001 From: Alexander Korotkov Date: Wed, 7 Jan 2026 16:29:58 +0200 Subject: [PATCH] Revert "Use WAIT FOR LSN in PostgreSQL::Test::Cluster::wait_for_catchup()" This reverts commit f30848cb05d4d63e1a5a2d6a9d72604f3b63370d. Due to buildfarm failures related to recovery conflicts while executing the WAIT FOR command. It appears that WAIT FOR still holds xmin for a while. Reported-by: Thomas Munro Discussion: https://postgr.es/m/CA%2BhUKG%2BL0OQR8dQtsNBSaA3FNNyQeFabdeRVzurm0b7Xtp592g%40mail.gmail.com --- src/test/perl/PostgreSQL/Test/Cluster.pm | 59 +----------------------- 1 file changed, 1 insertion(+), 58 deletions(-) diff --git a/src/test/perl/PostgreSQL/Test/Cluster.pm b/src/test/perl/PostgreSQL/Test/Cluster.pm index a28ea89aa10..955dfc0e7f8 100644 --- a/src/test/perl/PostgreSQL/Test/Cluster.pm +++ b/src/test/perl/PostgreSQL/Test/Cluster.pm @@ -3320,13 +3320,6 @@ If you pass an explicit value of target_lsn, it should almost always be the primary's write LSN; so this parameter is seldom needed except when querying some intermediate replication node rather than the primary. -When the standby is passed as a PostgreSQL::Test::Cluster instance and is -in recovery, this function uses the WAIT FOR LSN command on the standby -for modes replay, write, and flush. This is more efficient than polling -pg_stat_replication on the upstream, as WAIT FOR LSN uses a latch-based -wakeup mechanism. For 'sent' mode, or when the standby is passed as a -string (e.g., a subscription name), it falls back to polling. - If there is no active replication connection from this peer, waits until poll_query_until timeout. @@ -3346,13 +3339,10 @@ sub wait_for_catchup . join(', ', keys(%valid_modes)) unless exists($valid_modes{$mode}); - # Keep a reference to the standby node if passed as an object, so we can - # use WAIT FOR LSN on it later. - my $standby_node; + # Allow passing of a PostgreSQL::Test::Cluster instance as shorthand if (blessed($standby_name) && $standby_name->isa("PostgreSQL::Test::Cluster")) { - $standby_node = $standby_name; $standby_name = $standby_name->name; } if (!defined($target_lsn)) @@ -3377,53 +3367,6 @@ sub wait_for_catchup . $self->name . "\n"; # Before release 12 walreceiver just set the application name to # "walreceiver" - - # Use WAIT FOR LSN on the standby when: - # - The standby was passed as a Cluster object (so we can connect to it) - # - The mode is replay, write, or flush (not 'sent') - # - The standby is in recovery - # This is more efficient than polling pg_stat_replication on the upstream, - # as WAIT FOR LSN uses a latch-based wakeup mechanism. - if (defined($standby_node) && ($mode ne 'sent')) - { - my $standby_in_recovery = - $standby_node->safe_psql('postgres', "SELECT pg_is_in_recovery()"); - chomp($standby_in_recovery); - - if ($standby_in_recovery eq 't') - { - # Map mode names to WAIT FOR LSN mode names - my %mode_map = ( - 'replay' => 'standby_replay', - 'write' => 'standby_write', - 'flush' => 'standby_flush',); - my $wait_mode = $mode_map{$mode}; - my $timeout = $PostgreSQL::Test::Utils::timeout_default; - my $wait_query = - qq[WAIT FOR LSN '${target_lsn}' WITH (MODE '${wait_mode}', timeout '${timeout}s', no_throw);]; - my $output = $standby_node->safe_psql('postgres', $wait_query); - chomp($output); - - if ($output ne 'success') - { - # Fetch additional detail for debugging purposes - my $details = $self->safe_psql('postgres', - "SELECT * FROM pg_catalog.pg_stat_replication"); - diag qq(WAIT FOR LSN failed with status: - ${output}); - diag qq(Last pg_stat_replication contents: - ${details}); - croak "failed waiting for catchup"; - } - print "done\n"; - return; - } - } - - # Fall back to polling pg_stat_replication on the upstream for: - # - 'sent' mode (no corresponding WAIT FOR LSN mode) - # - When standby_name is a string (e.g., subscription name) - # - When the standby is no longer in recovery (was promoted) my $query = qq[SELECT '$target_lsn' <= ${mode}_lsn AND state = 'streaming' FROM pg_catalog.pg_stat_replication WHERE application_name IN ('$standby_name', 'walreceiver')];