diff --git a/server/src/main/java/org/elasticsearch/cluster/routing/allocation/allocator/BalancedShardsAllocator.java b/server/src/main/java/org/elasticsearch/cluster/routing/allocation/allocator/BalancedShardsAllocator.java index ed64520ce7e12..9b9af8143561c 100644 --- a/server/src/main/java/org/elasticsearch/cluster/routing/allocation/allocator/BalancedShardsAllocator.java +++ b/server/src/main/java/org/elasticsearch/cluster/routing/allocation/allocator/BalancedShardsAllocator.java @@ -862,17 +862,14 @@ public boolean moveShards() { for (var storedShardMovement : bestNonPreferredShardMovementsTracker.getBestShardMovements()) { final var shardRouting = storedShardMovement.shardRouting(); final var index = projectIndex(shardRouting); - // If `shardMoved` is true, there may have been moves that have made our previous move decision - // invalid, so we must call `decideMove` again. If not, we know we haven't made any moves, and we - // can use the cached decision. - final var moveDecision = shardMoved ? decideMove(index, shardRouting) : storedShardMovement.moveDecision(); + final var moveDecision = refreshDecisionIfRequired(index, storedShardMovement, shardMoved); if (moveDecision.isDecisionTaken() && moveDecision.cannotRemainAndCanMove()) { if (notPreferredLogger.isDebugEnabled()) { notPreferredLogger.debug( - "Moving shard [{}] to [{}] from a NOT_PREFERRED allocation, explanation is [{}]", + "Moving shard [{}] to [{}] from a NOT_PREFERRED allocation: {}", shardRouting, moveDecision.getTargetNode().getName(), - moveDecision.getCanRemainDecision().getExplanation() + moveDecision.getCanRemainDecision() ); } executeMove(shardRouting, index, moveDecision, "move-non-preferred"); @@ -886,6 +883,46 @@ public boolean moveShards() { return shardMoved; } + /** + * Re-run the allocation deciders if we need to + *

+ * Reasons to re-run the deciders include: + *

+ * + * @param index The index of the shard + * @param storedShardMovement The existing shard movement decision + * @param shardMoved True if a shard moved in this balancing round, false otherwise + * @return The move decision to act on, recalculated if necessary + */ + private MoveDecision refreshDecisionIfRequired( + ProjectIndex index, + BestShardMovementsTracker.StoredShardMovement storedShardMovement, + boolean shardMoved + ) { + if (notPreferredLogger.isDebugEnabled() == false && shardMoved == false) { + return storedShardMovement.moveDecision(); + } + + final var oldDebugMode = allocation.getDebugMode(); + if (notPreferredLogger.isDebugEnabled()) { + allocation.setDebugMode(RoutingAllocation.DebugMode.EXCLUDE_YES_DECISIONS); + } + try { + return decideMove(index, storedShardMovement.shardRouting()); + } finally { + allocation.setDebugMode(oldDebugMode); + } + } + private void executeMove(ShardRouting shardRouting, ProjectIndex index, MoveDecision moveDecision, String reason) { final ModelNode sourceNode = nodes.get(shardRouting.currentNodeId()); final ModelNode targetNode = nodes.get(moveDecision.getTargetNode().getId()); diff --git a/server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/BalancedShardsAllocatorTests.java b/server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/BalancedShardsAllocatorTests.java index 4afb83255da6f..eff18ab0faeb6 100644 --- a/server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/BalancedShardsAllocatorTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/routing/allocation/allocator/BalancedShardsAllocatorTests.java @@ -1027,7 +1027,7 @@ public Decision canRemain( RoutingNode node, RoutingAllocation allocation ) { - return new Decision.Single(Decision.Type.NOT_PREFERRED, "test_decider", "Always NOT_PREFERRED"); + return allocation.decision(Decision.NOT_PREFERRED, "test_decider", "Always NOT_PREFERRED"); } })), clusterState.getRoutingNodes().mutableCopy(), clusterState, ClusterInfo.EMPTY, SnapshotShardSizeInfo.EMPTY, 0L); @@ -1039,7 +1039,7 @@ public Decision canRemain( "moved a NOT_PREFERRED allocation", notPreferredLoggerName, Level.DEBUG, - "Moving shard [*] to [*] from a NOT_PREFERRED allocation, explanation is [Always NOT_PREFERRED]" + "Moving shard [*] to [*] from a NOT_PREFERRED allocation: [NOT_PREFERRED(Always NOT_PREFERRED)]" ) ); }