|
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