From 8560b6909bc1aa855bc1a48d3313a94e4501645e Mon Sep 17 00:00:00 2001 From: Mircea Cadariu Date: Tue, 18 Nov 2025 19:28:22 +0000 Subject: [PATCH v1] Test demonstrating pg_recvlogical receives duplicate data on reconnection When pg_recvlogical reconnects after losing connection, it can re-send already flushed data. This happens because the replication restart position is taken from the write position in the last status update, which may be older than the actual flushed position. This test documents the current behavior. A fix will be provided in a subsequent commit. --- src/bin/pg_basebackup/t/030_pg_recvlogical.pl | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/src/bin/pg_basebackup/t/030_pg_recvlogical.pl b/src/bin/pg_basebackup/t/030_pg_recvlogical.pl index 1b7a6f6f43..6249a2fc20 100644 --- a/src/bin/pg_basebackup/t/030_pg_recvlogical.pl +++ b/src/bin/pg_basebackup/t/030_pg_recvlogical.pl @@ -151,4 +151,65 @@ my $result = $node->safe_psql('postgres', ); is($result, 't', "failover is enabled for the new slot"); +# Test data re-transmission after disconnection +use IPC::Run qw(start); + +my $outfile = $node->basedir . '/reconnect.out'; + +$node->command_ok( + [ + 'pg_recvlogical', + '--slot' => 'reconnect_test', + '--dbname' => $node->connstr('postgres'), + '--create-slot', + ], + 'slot created for reconnection test'); + +$node->safe_psql('postgres', 'CREATE TABLE t(x int); INSERT INTO t VALUES (1);'); + +my $recv = start [ + 'pg_recvlogical', + '--slot', 'reconnect_test', + '--dbname', $node->connstr('postgres'), + '--start', + '--file', $outfile, + '--fsync-interval', '1', + '--status-interval', '10' +], '>', \my $out, '2>', \my $err; + +sleep(3); + +$recv->kill_kill(); + +# Check first INSERT was written +open(my $file, '<', $outfile); +my $content = ''; +while (<$file>) { $content = $content . $_; } +close($file); +ok($content =~ /INSERT.*:1/, 'first INSERT written to file'); + +# Insert second row +$node->safe_psql('postgres', 'INSERT INTO t VALUES (2);'); +my $endlsn = $node->safe_psql('postgres', 'SELECT pg_current_wal_lsn();'); + +$node->command_ok([ + 'pg_recvlogical', + '--slot', 'reconnect_test', + '--dbname', $node->connstr('postgres'), + '--start', + '--endpos', $endlsn, + '--file', $outfile +], 'second run after forced disconnect'); + +open(my $file2, '<', $outfile); +my $count = 0; +while (<$file2>) { + if (/INSERT/) { + $count = $count + 1; + } +} +close($file2); + +cmp_ok($count, '>', 2, 'more than two INSERT after disconnect'); + done_testing(); -- 2.39.5 (Apple Git-154)