From de3d8dc82cb4eefc1d516091f6fc5bd5dc9252cd Mon Sep 17 00:00:00 2001
From: Zhijie Hou <houzj.fnst@fujitsu.com>
Date: Tue, 25 Nov 2025 18:42:55 +0800
Subject: [PATCH v2] Fix test failure caused by commit 76b78721ca

The test failed because it assumed that a newly created logical
replication slot could be synced to the standby by the slotsync worker.
However, the presence of an existing physical slot caused the new logical
slot to use a non-latest xmin. On the standby, the DDL had already been
replayed, advancing xmin, which led to the slotsync worker failing to sync
the lagging logical slot.

To resolve this, we moved the slot sync statistics tests to run after the
tests that do not require the newly created slot to be sync-ready.
---
 .../t/040_standby_failover_slots_sync.pl      | 128 ++++++++++--------
 1 file changed, 70 insertions(+), 58 deletions(-)

diff --git a/src/test/recovery/t/040_standby_failover_slots_sync.pl b/src/test/recovery/t/040_standby_failover_slots_sync.pl
index b2bf5072bbf..7d3c82e0a29 100644
--- a/src/test/recovery/t/040_standby_failover_slots_sync.pl
+++ b/src/test/recovery/t/040_standby_failover_slots_sync.pl
@@ -213,75 +213,19 @@ is( $standby1->safe_psql(
 ##################################################
 # Test that the synchronized slot will be dropped if the corresponding remote
 # slot on the primary server has been dropped.
-#
-# Note: Both slots need to be dropped for the next test to work
 ##################################################
 
 $primary->psql('postgres', "SELECT pg_drop_replication_slot('lsub2_slot');");
-$primary->psql('postgres', "SELECT pg_drop_replication_slot('lsub1_slot');");
 
 $standby1->safe_psql('postgres', "SELECT pg_sync_replication_slots();");
 
 is( $standby1->safe_psql(
 		'postgres',
-		q{SELECT count(*) = 0 FROM pg_replication_slots WHERE slot_name IN ('lsub1_slot', 'lsub2_slot');}
+		q{SELECT count(*) = 0 FROM pg_replication_slots WHERE slot_name = 'lsub2_slot';}
 	),
 	"t",
 	'synchronized slot has been dropped');
 
-##################################################
-# Verify that slotsync skip statistics are correctly updated when the
-# slotsync operation is skipped.
-##################################################
-
-# Create a logical replication slot and create some DDL on the primary so
-# that the slot lags behind the standby.
-$primary->safe_psql(
-	'postgres', qq(
-	SELECT pg_create_logical_replication_slot('lsub1_slot', 'pgoutput', false, false, true);
-	CREATE TABLE wal_push(a int);
-));
-$primary->wait_for_replay_catchup($standby1);
-
-my $log_offset = -s $standby1->logfile;
-
-# Enable slot sync worker.
-$standby1->append_conf('postgresql.conf', qq(sync_replication_slots = on));
-$standby1->reload;
-
-# Confirm that the slot sync worker is able to start.
-$standby1->wait_for_log(qr/slot sync worker started/, $log_offset);
-
-# Confirm that the slot sync is skipped due to the remote slot lagging behind
-$standby1->wait_for_log(
-	qr/could not synchronize replication slot \"lsub1_slot\"/, $log_offset);
-
-# Confirm that the slotsync skip statistics is updated
-$result = $standby1->safe_psql('postgres',
-	"SELECT slotsync_skip_count > 0 FROM pg_stat_replication_slots WHERE slot_name = 'lsub1_slot'"
-);
-is($result, 't', "check slot sync skip count increments");
-
-# Clean the table
-$primary->safe_psql(
-	'postgres', qq(
-    DROP TABLE wal_push;
-));
-$primary->wait_for_replay_catchup($standby1);
-
-# Re-create the logical replication slot and sync it to standby for further tests
-$primary->safe_psql(
-	'postgres', qq(
-	SELECT pg_drop_replication_slot('lsub1_slot');
-	SELECT pg_create_logical_replication_slot('lsub1_slot', 'pgoutput', false, false, true);
-));
-$standby1->wait_for_log(
-	qr/newly created replication slot \"lsub1_slot\" is sync-ready now/,
-	$log_offset);
-
-$standby1->append_conf('postgresql.conf', qq(sync_replication_slots = off));
-$standby1->reload;
-
 ##################################################
 # Test that if the synchronized slot is invalidated while the remote slot is
 # still valid, the slot will be dropped and re-created on the standby by
@@ -337,7 +281,7 @@ $inactive_since_on_primary =
 # the failover slots.
 $primary->wait_for_replay_catchup($standby1);
 
-$log_offset = -s $standby1->logfile;
+my $log_offset = -s $standby1->logfile;
 
 # Synchronize the primary server slots to the standby.
 $standby1->safe_psql('postgres', "SELECT pg_sync_replication_slots();");
@@ -1043,4 +987,72 @@ $result = $standby1->safe_psql('postgres',
 
 is($result, '1', "data can be consumed using snap_test_slot");
 
+##################################################
+# Remove any unnecessary replication slots and clear pending transactions on the
+# primary server to ensure a clean environment.
+##################################################
+
+$primary->psql(
+	'postgres', qq(
+	SELECT pg_drop_replication_slot('sb1_slot');
+	SELECT pg_drop_replication_slot('lsub1_slot');
+	SELECT pg_drop_replication_slot('snap_test_slot');
+));
+
+$subscriber2->safe_psql('postgres', 'DROP SUBSCRIPTION regress_mysub2;');
+
+# Verify that all slots have been removed except the one necessary for standby2,
+# which is needed for further testing.
+is( $primary->safe_psql(
+		'postgres',
+		q{SELECT count(*) = 0 FROM pg_replication_slots WHERE slot_name != 'sb2_slot';}
+	),
+	"t",
+	'all replication slots have been dropped except the physical slot used by standby2'
+);
+
+# Commit the pending prepared transaction
+$primary->safe_psql('postgres', "COMMIT PREPARED 'test_twophase_slotsync';");
+$primary->wait_for_replay_catchup($standby2);
+
+##################################################
+# Verify that slotsync skip statistics are correctly updated when the
+# slotsync operation is skipped.
+##################################################
+
+# Create a logical replication slot and create some DDL on the primary so
+# that the slot lags behind the standby.
+$primary->safe_psql(
+	'postgres', qq(
+	SELECT pg_create_logical_replication_slot('lsub1_slot', 'pgoutput', false, false, true);
+	CREATE TABLE wal_push(a int);
+));
+$primary->wait_for_replay_catchup($standby2);
+
+$log_offset = -s $standby2->logfile;
+
+# Enable slot sync worker
+$standby2->append_conf(
+	'postgresql.conf', qq(
+hot_standby_feedback = on
+primary_conninfo = '$connstr_1 dbname=postgres'
+log_min_messages = 'debug2'
+sync_replication_slots = on
+));
+
+$standby2->reload;
+
+# Confirm that the slot sync worker is able to start.
+$standby2->wait_for_log(qr/slot sync worker started/, $log_offset);
+
+# Confirm that the slot sync is skipped due to the remote slot lagging behind
+$standby2->wait_for_log(
+	qr/could not synchronize replication slot \"lsub1_slot\"/, $log_offset);
+
+# Confirm that the slotsync skip statistics is updated
+$result = $standby2->safe_psql('postgres',
+	"SELECT slotsync_skip_count > 0 FROM pg_stat_replication_slots WHERE slot_name = 'lsub1_slot'"
+);
+is($result, 't', "check slot sync skip count increments");
+
 done_testing();
-- 
2.51.1.windows.1

