From 760d524980b76cccc738c0b2b434f24f1c159d7a Mon Sep 17 00:00:00 2001
From: Fujii Masao <fujii@postgresql.org>
Date: Thu, 4 Sep 2025 22:23:24 +0900
Subject: [PATCH v2 1/2] pg_recvlogical: Prevent flushed data from being
 re-sent.

Previously, when pg_recvlogical lost connection, reconnected, and restarted
replication, data that had already been flushed could be streamed again.
This happened because the replication start position used when restarting
replication was taken from the last standby status message, which could be
older than the position of the last flushed data. As a result, some flushed
data newer than the replication start position could exist and be re-sent.

This commit fixes the issue by ensuring all written data is flushed to disk
before restarting replication, and by using the last flushed position as
the replication start point. This prevents already flushed data from being
re-sent.

Additionally, previously when the --no-loop option was used, pg_recvlogical
could exit without flushing written data, potentially losing data. To fix
this issue, this commit also ensures all data is flushed to disk before
exiting due to --no-loop.
---
 src/bin/pg_basebackup/pg_recvlogical.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/src/bin/pg_basebackup/pg_recvlogical.c b/src/bin/pg_basebackup/pg_recvlogical.c
index 14ad1504678..0354173bcbc 100644
--- a/src/bin/pg_basebackup/pg_recvlogical.c
+++ b/src/bin/pg_basebackup/pg_recvlogical.c
@@ -191,6 +191,13 @@ OutputFsync(TimestampTz now)
 
 	output_fsync_lsn = output_written_lsn;
 
+	/*
+	 * Save the last flushed position as the replication start point. On
+	 * reconnect, replication resumes from there to avoid re-sending flushed
+	 * data.
+	 */
+	startpos = output_fsync_lsn;
+
 	if (fsync_interval <= 0)
 		return true;
 
@@ -1025,8 +1032,18 @@ main(int argc, char **argv)
 			 */
 			exit(0);
 		}
-		else if (noloop)
+
+		/*
+		 * Ensure all written data is flushed to disk before exiting or
+		 * starting a new replication.
+		 */
+		if (outfd != -1 && strcmp(outfile, "-") != 0)
+			OutputFsync(feGetCurrentTimestamp());
+
+		if (noloop)
+		{
 			pg_fatal("disconnected");
+		}
 		else
 		{
 			/* translator: check source for value for %d */
-- 
2.51.2

