v6-0004-Use-WAIT-FOR-LSN-in.patch
application/octet-stream
Filename: v6-0004-Use-WAIT-FOR-LSN-in.patch
Type: application/octet-stream
Part: 3
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v6-0004
Subject: Use WAIT FOR LSN in PostgreSQL::Test::Cluster::wait_for_catchup()
| File | + | − |
|---|---|---|
| src/test/perl/PostgreSQL/Test/Cluster.pm | 32 | 3 |
From 7265330a02c5d966ef42cce3f9c15f4acae37ff4 Mon Sep 17 00:00:00 2001
From: alterego655 <824662526@qq.com>
Date: Tue, 16 Dec 2025 11:03:23 +0800
Subject: [PATCH v6 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 | 35 ++++++++++++++++++++++--
1 file changed, 32 insertions(+), 3 deletions(-)
diff --git a/src/test/perl/PostgreSQL/Test/Cluster.pm b/src/test/perl/PostgreSQL/Test/Cluster.pm
index 295988b8b87..eec8233b515 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,35 @@ 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;
+ # Map mode names to WAIT FOR LSN MODE values (uppercase)
+ my $wait_mode = uc($mode);
+ my $query =
+ qq[WAIT FOR LSN '${target_lsn}' MODE ${wait_mode} WITH (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