|
55 | 55 | import java.util.concurrent.atomic.AtomicBoolean; |
56 | 56 | import java.util.concurrent.atomic.AtomicInteger; |
57 | 57 | import java.util.function.Function; |
58 | | -import java.util.stream.Collectors; |
59 | 58 |
|
| 59 | +import static java.util.stream.Collectors.toMap; |
60 | 60 | import static org.elasticsearch.cluster.node.DiscoveryNodeRole.DATA_COLD_NODE_ROLE; |
61 | 61 | import static org.elasticsearch.cluster.node.DiscoveryNodeRole.DATA_FROZEN_NODE_ROLE; |
62 | 62 | import static org.elasticsearch.cluster.node.DiscoveryNodeRole.DATA_HOT_NODE_ROLE; |
@@ -450,6 +450,32 @@ public void testRetryMovedShard() { |
450 | 450 | assertThat(attempt.get(), equalTo(3)); |
451 | 451 | } |
452 | 452 |
|
| 453 | + public void testRetryMultipleMovedShards() { |
| 454 | + var attempt = new AtomicInteger(0); |
| 455 | + var response = safeGet( |
| 456 | + sendRequests( |
| 457 | + randomBoolean(), |
| 458 | + -1, |
| 459 | + List.of(targetShard(shard1, node1), targetShard(shard2, node2), targetShard(shard3, node3)), |
| 460 | + shardIds -> shardIds.stream().collect(toMap(Function.identity(), shardId -> List.of(randomFrom(node1, node2, node3)))), |
| 461 | + (node, shardIds, aliasFilters, listener) -> runWithDelay( |
| 462 | + () -> listener.onResponse( |
| 463 | + attempt.incrementAndGet() <= 6 |
| 464 | + ? new DataNodeComputeResponse( |
| 465 | + DriverCompletionInfo.EMPTY, |
| 466 | + shardIds.stream().collect(toMap(Function.identity(), ShardNotFoundException::new)) |
| 467 | + ) |
| 468 | + : new DataNodeComputeResponse(DriverCompletionInfo.EMPTY, Map.of()) |
| 469 | + ) |
| 470 | + ) |
| 471 | + ) |
| 472 | + ); |
| 473 | + assertThat(response.totalShards, equalTo(3)); |
| 474 | + assertThat(response.successfulShards, equalTo(3)); |
| 475 | + assertThat(response.skippedShards, equalTo(0)); |
| 476 | + assertThat(response.failedShards, equalTo(0)); |
| 477 | + } |
| 478 | + |
453 | 479 | public void testDoesNotRetryMovedShardIndefinitely() { |
454 | 480 | var attempt = new AtomicInteger(0); |
455 | 481 | var response = safeGet(sendRequests(true, -1, List.of(targetShard(shard1, node1)), shardIds -> { |
@@ -517,28 +543,28 @@ public void testRetryUnassignedShardWithoutPartialResults() { |
517 | 543 |
|
518 | 544 | ); |
519 | 545 | expectThrows(NoShardAvailableActionException.class, containsString("no such shard"), future::actionGet); |
| 546 | + assertThat(attempt.get(), equalTo(1)); |
520 | 547 | } |
521 | 548 |
|
522 | 549 | public void testRetryUnassignedShardWithPartialResults() { |
523 | | - var response = safeGet( |
524 | | - sendRequests( |
525 | | - true, |
526 | | - -1, |
527 | | - List.of(targetShard(shard1, node1), targetShard(shard2, node2)), |
528 | | - shardIds -> Map.of(shard1, List.of()), |
529 | | - (node, shardIds, aliasFilters, listener) -> runWithDelay( |
530 | | - () -> listener.onResponse( |
531 | | - Objects.equals(shardIds, List.of(shard2)) |
532 | | - ? new DataNodeComputeResponse(DriverCompletionInfo.EMPTY, Map.of()) |
533 | | - : new DataNodeComputeResponse(DriverCompletionInfo.EMPTY, Map.of(shard1, new ShardNotFoundException(shard1))) |
534 | | - ) |
| 550 | + var attempt = new AtomicInteger(0); |
| 551 | + var response = safeGet(sendRequests(true, -1, List.of(targetShard(shard1, node1), targetShard(shard2, node2)), shardIds -> { |
| 552 | + attempt.incrementAndGet(); |
| 553 | + return Map.of(shard1, List.of()); |
| 554 | + }, |
| 555 | + (node, shardIds, aliasFilters, listener) -> runWithDelay( |
| 556 | + () -> listener.onResponse( |
| 557 | + Objects.equals(shardIds, List.of(shard2)) |
| 558 | + ? new DataNodeComputeResponse(DriverCompletionInfo.EMPTY, Map.of()) |
| 559 | + : new DataNodeComputeResponse(DriverCompletionInfo.EMPTY, Map.of(shard1, new ShardNotFoundException(shard1))) |
535 | 560 | ) |
536 | 561 | ) |
537 | | - ); |
| 562 | + )); |
538 | 563 | assertThat(response.totalShards, equalTo(2)); |
539 | 564 | assertThat(response.successfulShards, equalTo(1)); |
540 | 565 | assertThat(response.skippedShards, equalTo(0)); |
541 | 566 | assertThat(response.failedShards, equalTo(1)); |
| 567 | + assertThat(attempt.get(), equalTo(1)); |
542 | 568 | } |
543 | 569 |
|
544 | 570 | static DataNodeRequestSender.TargetShard targetShard(ShardId shardId, DiscoveryNode... nodes) { |
@@ -621,11 +647,7 @@ PlainActionFuture<ComputeResponse> sendRequests( |
621 | 647 | void searchShards(Set<String> concreteIndices, ActionListener<TargetShards> listener) { |
622 | 648 | runWithDelay( |
623 | 649 | () -> listener.onResponse( |
624 | | - new TargetShards( |
625 | | - shards.stream().collect(Collectors.toMap(TargetShard::shardId, Function.identity())), |
626 | | - shards.size(), |
627 | | - 0 |
628 | | - ) |
| 650 | + new TargetShards(shards.stream().collect(toMap(TargetShard::shardId, Function.identity())), shards.size(), 0) |
629 | 651 | ) |
630 | 652 | ); |
631 | 653 | } |
|
0 commit comments