From cd5a916631b4d34884cde3aa6f29f12427146bc9 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 v1] 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..8e682b88ead 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");
 
+##################################################
+# Verify that slotsync skip statistics are correctly updated when the
+# slotsync operation is skipped.
+##################################################
+
+# Enable slot sync on standby2
+$standby2->append_conf('postgresql.conf', qq(
+hot_standby_feedback = on
+primary_conninfo = '$connstr_1 dbname=postgres'
+log_min_messages = 'debug2'
+));
+
+$standby2->reload;
+
+# Commit the pending prepared transaction
+$primary->safe_psql('postgres', "COMMIT PREPARED 'test_twophase_slotsync';");
+$primary->wait_for_replay_catchup($standby2);
+
+# Remove all logical replication slots on the primary server to ensure the
+# corresponding synced slots are also removed. This guarantees that the safest
+# catalog_xmin on the standby is not preserved by existing slots, allowing newly
+# created slots to have a fresher initial catalog_xmin.
+$primary->psql('postgres', qq(
+	SELECT pg_drop_replication_slot('lsub1_slot');
+	SELECT pg_drop_replication_slot('snap_test_slot');
+));
+
+$subscriber2->safe_psql(
+	'postgres', 'DROP SUBSCRIPTION regress_mysub2;');
+
+$standby2->safe_psql('postgres', "SELECT pg_sync_replication_slots();");
+
+is( $standby2->safe_psql(
+		'postgres',
+		q{SELECT count(*) = 0 FROM pg_replication_slots WHERE slot_name IN ('lsub1_slot', 'lsub2_slot', 'snap_test_slot');}
+	),
+	"t",
+	'synchronized slot has been dropped');
+
+# 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(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

