v7-0004-Use-WAIT-FOR-LSN-in.patch
application/octet-stream
Filename: v7-0004-Use-WAIT-FOR-LSN-in.patch
Type: application/octet-stream
Part: 1
From 9dde4e330844d827f783ab2caca505036ac884b0 Mon Sep 17 00:00:00 2001
From: alterego655 <824662526@qq.com>
Date: Tue, 16 Dec 2025 11:03:23 +0800
Subject: [PATCH v7 4/4] Use WAIT FOR LSN in
PostgreSQL::Test::Cluster::wait_for_catchup()
Replace polling-based catchup waiting with WAIT FOR LSN command when
running on a standby server. This is more efficient than repeatedly
querying pg_stat_replication as the WAIT FOR command uses the latch-
based wakeup mechanism.
The optimization applies when:
- The node is in recovery (standby server)
- The mode is 'replay', 'write', or 'flush' (not 'sent')
For 'sent' mode or when running on a primary, the function falls back
to the original polling approach since WAIT FOR LSN is only available
during recovery.
---
src/test/perl/PostgreSQL/Test/Cluster.pm | 33 +++++++++++++++++++++---
1 file changed, 30 insertions(+), 3 deletions(-)
diff --git a/src/test/perl/PostgreSQL/Test/Cluster.pm b/src/test/perl/PostgreSQL/Test/Cluster.pm
index 295988b8b87..276350c5f13 100644
--- a/src/test/perl/PostgreSQL/Test/Cluster.pm
+++ b/src/test/perl/PostgreSQL/Test/Cluster.pm
@@ -3335,6 +3335,9 @@ sub wait_for_catchup
$mode = defined($mode) ? $mode : 'replay';
my %valid_modes =
('sent' => 1, 'write' => 1, 'flush' => 1, 'replay' => 1);
+ my $isrecovery =
+ $self->safe_psql('postgres', "SELECT pg_is_in_recovery()");
+ chomp($isrecovery);
croak "unknown mode $mode for 'wait_for_catchup', valid modes are "
. join(', ', keys(%valid_modes))
unless exists($valid_modes{$mode});
@@ -3347,9 +3350,6 @@ sub wait_for_catchup
}
if (!defined($target_lsn))
{
- my $isrecovery =
- $self->safe_psql('postgres', "SELECT pg_is_in_recovery()");
- chomp($isrecovery);
if ($isrecovery eq 't')
{
$target_lsn = $self->lsn('replay');
@@ -3367,6 +3367,33 @@ sub wait_for_catchup
. $self->name . "\n";
# Before release 12 walreceiver just set the application name to
# "walreceiver"
+
+ # Use WAIT FOR LSN when in recovery for supported modes (replay, write, flush)
+ # This is more efficient than polling pg_stat_replication
+ if (($mode ne 'sent') && ($isrecovery eq 't'))
+ {
+ my $timeout = $PostgreSQL::Test::Utils::timeout_default;
+ my $query =
+ qq[WAIT FOR LSN '${target_lsn}' WITH (MODE '${mode}', timeout '${timeout}s', no_throw);];
+ my $output = $self->safe_psql('postgres', $query);
+ chomp($output);
+
+ if ($output ne 'success')
+ {
+ # Fetch additional detail for debugging purposes
+ $query = qq[SELECT * FROM pg_catalog.pg_stat_replication];
+ my $details = $self->safe_psql('postgres', $query);
+ 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;
+ }
+
+ # Polling for 'sent' mode or when not in recovery (WAIT FOR LSN not applicable)
my $query = qq[SELECT '$target_lsn' <= ${mode}_lsn AND state = 'streaming'
FROM pg_catalog.pg_stat_replication
WHERE application_name IN ('$standby_name', 'walreceiver')];
--
2.51.0