From 6420ae1112818ed7e4f4d5ecd306ef10f8873556 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Fri, 28 Aug 2020 16:35:25 +1200
Subject: [PATCH v2 3/3] Optionally, don't wait for end-of-recovery checkpoint.

Add a GUC to specify whether you want to wait for the end-of-recovery
checkpoint to complete before continuing.  Default to the traditional
behavior, "on".

XXX This probably needs a better GUC name.  There may also be problems with
timelines; see the nearby fast promotion code.

XXX This is experimental code only!  There may be fundamental problems
with the concept.  Or not.
---
 src/backend/access/transam/xlog.c | 23 +++++++++++++++--------
 src/backend/utils/misc/guc.c      |  9 +++++++++
 src/include/access/xlog.h         |  1 +
 3 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index b10b1b614a..4c001c466b 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -111,6 +111,7 @@ int			CommitSiblings = 5; /* # concurrent xacts needed to sleep */
 int			wal_retrieve_retry_interval = 5000;
 int			max_slot_wal_keep_size_mb = -1;
 bool		track_wal_io_timing = false;
+bool		end_of_recovery_checkpoint_wait = true;
 
 #ifdef WAL_DEBUG
 bool		XLOG_DEBUG = false;
@@ -7874,6 +7875,18 @@ StartupXLOG(void)
 
 	if (InRecovery)
 	{
+		int		checkpoint_flags = CHECKPOINT_IMMEDIATE;
+
+		/*
+		 * Should we wait for the end-of-recovery checkpoint to complete?
+		 * Traditionally we do this, but it may be useful to allow connections
+		 * sooner.
+		 */
+		if (end_of_recovery_checkpoint_wait)
+			checkpoint_flags |= CHECKPOINT_END_OF_RECOVERY | CHECKPOINT_WAIT;
+		else
+			checkpoint_flags |= CHECKPOINT_FORCE;
+
 		/*
 		 * Perform a checkpoint to update all our recovery activity to disk.
 		 *
@@ -7919,16 +7932,10 @@ StartupXLOG(void)
 			}
 
 			if (!promoted)
-				RequestCheckpoint(CHECKPOINT_END_OF_RECOVERY |
-								  CHECKPOINT_IMMEDIATE |
-								  CHECKPOINT_WAIT);
+				RequestCheckpoint(checkpoint_flags);
 		}
 		else
-		{
-			RequestCheckpoint(CHECKPOINT_END_OF_RECOVERY |
-							  CHECKPOINT_IMMEDIATE |
-							  CHECKPOINT_WAIT);
-		}
+			RequestCheckpoint(checkpoint_flags);
 	}
 
 	if (ArchiveRecoveryRequested)
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 855076b1fd..e59194a3f8 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -2058,6 +2058,15 @@ static struct config_bool ConfigureNamesBool[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"end_of_recovery_checkpoint_wait", PGC_SIGHUP, WAL_CHECKPOINTS,
+			gettext_noop("Whether to wait for the end-of-recovery checkpoint to complete."),
+		},
+		&end_of_recovery_checkpoint_wait,
+		true,
+		NULL, NULL, NULL
+	},
+
 	/* End-of-list marker */
 	{
 		{NULL, 0, 0, NULL, NULL}, NULL, false, NULL, NULL, NULL
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index 6d384d3ce6..77b4560f4b 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -132,6 +132,7 @@ extern char *PrimaryConnInfo;
 extern char *PrimarySlotName;
 extern bool wal_receiver_create_temp_slot;
 extern bool track_wal_io_timing;
+extern bool end_of_recovery_checkpoint_wait;
 
 /* indirectly set via GUC system */
 extern TransactionId recoveryTargetXid;
-- 
2.30.1

