From 7420f3194939e08219634ff079a72671766698ad Mon Sep 17 00:00:00 2001
From: Manuel Reyes Bravo <manuelreyesbravo@gmail.com>
Date: Fri, 2 Oct 2026 22:45:09 -0300
Subject: [PATCH v2 2/2] reindexdb: keep --jobs parallel and stop on cancel
 with --concurrently

Only wait for each command when the next index belongs to the same
table.  An index that is the only one of its table goes through the
usual asynchronous path, so indexes of different tables are again
processed in parallel.

Also stop at the first failure or cancel request, as the other paths
do, instead of going on with the remaining indexes of the table.
---
 src/bin/scripts/reindexdb.c | 37 ++++++++++++++++++++++---------------
 1 file changed, 22 insertions(+), 15 deletions(-)

diff --git a/src/bin/scripts/reindexdb.c b/src/bin/scripts/reindexdb.c
index d7784de3f55..4002616cd8f 100644
--- a/src/bin/scripts/reindexdb.c
+++ b/src/bin/scripts/reindexdb.c
@@ -458,7 +458,9 @@ reindex_one_database(ConnParams *cparams, ReindexType type,
 			run_reindex_command(free_slot->connection, process_type, objname,
 								echo, &sql);
 		}
-		else if (parallel && process_type == REINDEX_INDEX)
+		else if (parallel && process_type == REINDEX_INDEX &&
+				 indices_tables_cell->next &&
+				 indices_tables_cell->val == indices_tables_cell->next->val)
 		{
 			/*
 			 * REINDEX CONCURRENTLY cannot run in a transaction block, so it
@@ -469,32 +471,37 @@ reindex_one_database(ConnParams *cparams, ReindexType type,
 			 * which could deadlock.  So, each command is sent separately,
 			 * waiting for it to complete before sending the next one.
 			 */
-			gen_reindex_command(free_slot->connection, process_type, objname,
-								echo, verbose, concurrently, tablespace, &sql);
-			run_reindex_command(free_slot->connection, process_type, objname,
-								echo, &sql);
-			if (!consumeQueryResult(free_slot))
-				failed = true;
-			while (indices_tables_cell->next &&
-				   indices_tables_cell->val == indices_tables_cell->next->val)
+			for (;;)
 			{
-				indices_tables_cell = indices_tables_cell->next;
-				cell = cell->next;
-				objname = cell->val;
-				termPQExpBuffer(&sql);
-				initPQExpBuffer(&sql);
 				gen_reindex_command(free_slot->connection, process_type, objname,
 									echo, verbose, concurrently, tablespace, &sql);
 				run_reindex_command(free_slot->connection, process_type, objname,
 									echo, &sql);
-				if (!consumeQueryResult(free_slot))
+
+				/* Stop at the first failure or cancel, as the other paths do. */
+				if (!consumeQueryResult(free_slot) || CancelRequested)
+				{
+					termPQExpBuffer(&sql);
 					failed = true;
+					goto finish;
+				}
+
+				if (!(indices_tables_cell->next &&
+					  indices_tables_cell->val == indices_tables_cell->next->val))
+					break;
+				indices_tables_cell = indices_tables_cell->next;
+				cell = cell->next;
+				objname = cell->val;
+				resetPQExpBuffer(&sql);
 			}
 			indices_tables_cell = indices_tables_cell->next;
 			ParallelSlotSetIdle(free_slot);
 		}
 		else
 		{
+			/* The only index of its table: nothing to keep in order. */
+			if (parallel && process_type == REINDEX_INDEX)
+				indices_tables_cell = indices_tables_cell->next;
 			gen_reindex_command(free_slot->connection, process_type, objname,
 								echo, verbose, concurrently, tablespace, &sql);
 			run_reindex_command(free_slot->connection, process_type, objname,
-- 
2.55.0

