v20-0011-Detect-the-disconnection-from-the-primary-during.patch

application/octet-stream

Filename: v20-0011-Detect-the-disconnection-from-the-primary-during.patch
Type: application/octet-stream
Part: 10
Message: RE: speed up a logical replica setup

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: format-patch
Series: patch v20-0011
Subject: Detect the disconnection from the primary during the recovery
File+
src/bin/pg_basebackup/pg_createsubscriber.c 13 2
From f04540339130d0c06998dd5f2bc9b7eedba5d3f3 Mon Sep 17 00:00:00 2001
From: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Date: Thu, 15 Feb 2024 02:47:38 +0000
Subject: [PATCH v20 11/12] Detect the disconnection from the primary during
 the recovery

Previously, the wait_for_end_recovery() function would indefinitely wait for a
server to exit recovery mode, without considering scenarios where the server
might be disconnected from the primary. This could lead to situations where the
server never reaches a consistent state, as it remains unaware of its
disconnection.

This patch introduces a new check within the wait_for_end_recovery() process,
leveraging the pg_stat_wal_receiver system view to verify the presence of an
active walreceiver process. While this method does not account for potential
frequent restarts of the walreceiver, it provides a straightforward and effective
means to detect disconnections from the primary server during the recovery phase.
---
 src/bin/pg_basebackup/pg_createsubscriber.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/src/bin/pg_basebackup/pg_createsubscriber.c b/src/bin/pg_basebackup/pg_createsubscriber.c
index db088024d3..2458c874e5 100644
--- a/src/bin/pg_basebackup/pg_createsubscriber.c
+++ b/src/bin/pg_basebackup/pg_createsubscriber.c
@@ -1209,9 +1209,12 @@ wait_for_end_recovery(const char *conninfo, const char *pg_bin_dir,
 
 	for (;;)
 	{
-		bool		in_recovery;
+		bool		in_recovery,
+					still_alive;
 
-		res = PQexec(conn, "SELECT pg_catalog.pg_is_in_recovery()");
+		res = PQexec(conn,
+					"SELECT pg_catalog.pg_is_in_recovery(), count(pid) "
+					"FROM pg_catalog.pg_stat_wal_receiver;");
 
 		if (PQresultStatus(res) != PGRES_TUPLES_OK)
 			pg_fatal("could not obtain recovery progress");
@@ -1220,6 +1223,7 @@ wait_for_end_recovery(const char *conninfo, const char *pg_bin_dir,
 			pg_fatal("unexpected result from pg_is_in_recovery function");
 
 		in_recovery = (strcmp(PQgetvalue(res, 0, 0), "t") == 0);
+		still_alive = (strcmp(PQgetvalue(res, 0, 0), "t") == 0);
 
 		PQclear(res);
 
@@ -1233,6 +1237,13 @@ wait_for_end_recovery(const char *conninfo, const char *pg_bin_dir,
 			break;
 		}
 
+		/* Bail out if we have disconnected from the primary */
+		if (!still_alive)
+		{
+			stop_standby_server(pg_bin_dir, opt->subscriber_dir);
+			pg_fatal("disconnected from the primary while waiting the end of recovery");
+		}
+
 		/* Bail out after recovery_timeout seconds if this option is set */
 		if (opt->recovery_timeout > 0 && timer >= opt->recovery_timeout)
 		{
-- 
2.43.0