Skip to content

Commit d575db0

Browse files
authored
[8.x] Skip eager reconciliation for empty routing table (#116903) (#117103)
* Skip eager reconciliation for empty routing table (#116903) No need to start the eager reconciliation when the routing table is empty. An empty routing table means either the cluster has no shards or the state has not recovered. The eager reconciliation is not necessary in both cases. Resolves: #115885 * fix compilation
1 parent 6609e73 commit d575db0

File tree

2 files changed

+82
-0
lines changed

2 files changed

+82
-0
lines changed

server/src/main/java/org/elasticsearch/cluster/routing/allocation/allocator/DesiredBalanceShardsAllocator.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,10 @@ protected void processInput(DesiredBalanceInput desiredBalanceInput) {
124124

125125
recordTime(
126126
cumulativeComputationTime,
127+
// We set currentDesiredBalance back to INITIAL when the node stands down as master in onNoLongerMaster.
128+
// However, it is possible that we revert the effect here by setting it again since the computation is async
129+
// and does not check whether the node is master. This should have little to no practical impact. But it may
130+
// lead to unexpected behaviours for tests. See also https://github.com/elastic/elasticsearch/pull/116904
127131
() -> setCurrentDesiredBalance(
128132
desiredBalanceComputer.compute(
129133
getInitialDesiredBalance(),
@@ -202,6 +206,10 @@ public void allocate(RoutingAllocation allocation, ActionListener<Void> listener
202206
queue.add(index, listener);
203207
desiredBalanceComputation.onNewInput(DesiredBalanceInput.create(index, allocation));
204208

209+
if (allocation.routingTable().indicesRouting().isEmpty()) {
210+
logger.debug("No eager reconciliation needed for empty routing table");
211+
return;
212+
}
205213
// Starts reconciliation towards desired balance that might have not been updated with a recent calculation yet.
206214
// This is fine as balance should have incremental rather than radical changes.
207215
// This should speed up achieving the desired balance in cases current state is still different from it (due to THROTTLING).

server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/DesiredBalanceShardsAllocatorTests.java

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.apache.lucene.util.SetOnce;
1414
import org.elasticsearch.action.ActionListener;
1515
import org.elasticsearch.action.support.ActionTestUtils;
16+
import org.elasticsearch.action.support.PlainActionFuture;
1617
import org.elasticsearch.cluster.ClusterInfo;
1718
import org.elasticsearch.cluster.ClusterName;
1819
import org.elasticsearch.cluster.ClusterState;
@@ -56,6 +57,7 @@
5657
import org.elasticsearch.test.MockLog;
5758
import org.elasticsearch.threadpool.TestThreadPool;
5859

60+
import java.util.Collections;
5961
import java.util.List;
6062
import java.util.Map;
6163
import java.util.Queue;
@@ -78,7 +80,9 @@
7880
import static org.hamcrest.Matchers.equalTo;
7981
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
8082
import static org.hamcrest.Matchers.hasItem;
83+
import static org.hamcrest.Matchers.is;
8184
import static org.hamcrest.Matchers.not;
85+
import static org.hamcrest.Matchers.sameInstance;
8286

8387
public class DesiredBalanceShardsAllocatorTests extends ESAllocationTestCase {
8488

@@ -906,6 +910,76 @@ public void resetDesiredBalance() {
906910
}
907911
}
908912

913+
public void testNotReconcileEagerlyForEmptyRoutingTable() {
914+
final var threadPool = new TestThreadPool(getTestName());
915+
final var clusterService = ClusterServiceUtils.createClusterService(ClusterState.EMPTY_STATE, threadPool);
916+
final var clusterSettings = createBuiltInClusterSettings();
917+
final var shardsAllocator = createShardsAllocator();
918+
final var reconciliationTaskSubmitted = new AtomicBoolean();
919+
final var desiredBalanceShardsAllocator = new DesiredBalanceShardsAllocator(
920+
shardsAllocator,
921+
threadPool,
922+
clusterService,
923+
new DesiredBalanceComputer(clusterSettings, threadPool, shardsAllocator) {
924+
@Override
925+
public DesiredBalance compute(
926+
DesiredBalance previousDesiredBalance,
927+
DesiredBalanceInput desiredBalanceInput,
928+
Queue<List<MoveAllocationCommand>> pendingDesiredBalanceMoves,
929+
Predicate<DesiredBalanceInput> isFresh
930+
) {
931+
assertThat(previousDesiredBalance, sameInstance(DesiredBalance.INITIAL));
932+
return new DesiredBalance(desiredBalanceInput.index(), Map.of());
933+
}
934+
},
935+
(clusterState, rerouteStrategy) -> null,
936+
TelemetryProvider.NOOP
937+
) {
938+
939+
private ActionListener<Void> lastListener;
940+
941+
@Override
942+
public void allocate(RoutingAllocation allocation, ActionListener<Void> listener) {
943+
lastListener = listener;
944+
super.allocate(allocation, listener);
945+
}
946+
947+
@Override
948+
protected void reconcile(DesiredBalance desiredBalance, RoutingAllocation allocation) {
949+
fail("should not call reconcile");
950+
}
951+
952+
@Override
953+
protected void submitReconcileTask(DesiredBalance desiredBalance) {
954+
assertThat(desiredBalance.lastConvergedIndex(), equalTo(0L));
955+
reconciliationTaskSubmitted.set(true);
956+
lastListener.onResponse(null);
957+
}
958+
};
959+
assertThat(desiredBalanceShardsAllocator.getDesiredBalance(), sameInstance(DesiredBalance.INITIAL));
960+
try {
961+
final PlainActionFuture<Void> future = new PlainActionFuture<>();
962+
desiredBalanceShardsAllocator.allocate(
963+
new RoutingAllocation(
964+
new AllocationDeciders(Collections.emptyList()),
965+
clusterService.state(),
966+
null,
967+
null,
968+
randomNonNegativeLong()
969+
),
970+
future
971+
);
972+
safeGet(future);
973+
assertThat(desiredBalanceShardsAllocator.getStats().computationSubmitted(), equalTo(1L));
974+
assertThat(desiredBalanceShardsAllocator.getStats().computationExecuted(), equalTo(1L));
975+
assertThat(reconciliationTaskSubmitted.get(), is(true));
976+
assertThat(desiredBalanceShardsAllocator.getDesiredBalance().lastConvergedIndex(), equalTo(0L));
977+
} finally {
978+
clusterService.close();
979+
terminate(threadPool);
980+
}
981+
}
982+
909983
private static IndexMetadata createIndex(String name) {
910984
return IndexMetadata.builder(name).settings(indexSettings(IndexVersion.current(), 1, 0)).build();
911985
}

0 commit comments

Comments
 (0)