From e24a00603080d476087b8e327284d849f72d86a8 Mon Sep 17 00:00:00 2001
From: alterego655 <824662526@qq.com>
Date: Wed, 12 Nov 2025 13:32:05 +0800
Subject: [PATCH v2] Use WAIT FOR LSN in 
 PostgreSQL::Test::Cluster::wait_for_catchup()

---
 src/test/perl/PostgreSQL/Test/Cluster.pm | 32 +++++++++++++++++++++---
 1 file changed, 29 insertions(+), 3 deletions(-)

diff --git a/src/test/perl/PostgreSQL/Test/Cluster.pm b/src/test/perl/PostgreSQL/Test/Cluster.pm
index 35413f14019..41784553d4b 100644
--- a/src/test/perl/PostgreSQL/Test/Cluster.pm
+++ b/src/test/perl/PostgreSQL/Test/Cluster.pm
@@ -3328,6 +3328,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});
@@ -3340,9 +3343,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');
@@ -3360,6 +3360,32 @@ sub wait_for_catchup
 	  . $self->name . "\n";
 	# Before release 12 walreceiver just set the application name to
 	# "walreceiver"
+
+	# Use WAIT FOR LSN when appropriate
+	if (($mode eq 'replay') && ($isrecovery eq 't'))
+	{
+		my $timeout = $PostgreSQL::Test::Utils::timeout_default;
+		my $query =
+		  qq[WAIT FOR LSN '${target_lsn}' 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 other modes or when WAIT FOR LSN is 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

