|
6 | 6 | package org.elasticsearch.xpack.ccr.action; |
7 | 7 |
|
8 | 8 | import org.elasticsearch.ElasticsearchException; |
| 9 | +import org.elasticsearch.action.ActionListener; |
9 | 10 | import org.elasticsearch.common.UUIDs; |
10 | 11 | import org.elasticsearch.common.collect.Tuple; |
11 | 12 | import org.elasticsearch.common.settings.Settings; |
@@ -79,6 +80,7 @@ public class ShardFollowNodeTaskTests extends ESTestCase { |
79 | 80 | private Queue<Long> followerGlobalCheckpoints; |
80 | 81 | private Queue<Long> maxSeqNos; |
81 | 82 | private Queue<Integer> responseSizes; |
| 83 | + private Queue<ActionListener<BulkShardOperationsResponse>> pendingBulkShardRequests; |
82 | 84 |
|
83 | 85 | public void testCoordinateReads() { |
84 | 86 | ShardFollowTaskParams params = new ShardFollowTaskParams(); |
@@ -599,6 +601,55 @@ public void testReceiveNothingExpectedSomething() { |
599 | 601 | assertThat(status.leaderGlobalCheckpoint(), equalTo(63L)); |
600 | 602 | } |
601 | 603 |
|
| 604 | + public void testHandlePartialResponses() { |
| 605 | + ShardFollowTaskParams params = new ShardFollowTaskParams(); |
| 606 | + params.maxReadRequestOperationCount = 10; |
| 607 | + params.maxOutstandingReadRequests = 2; |
| 608 | + params.maxOutstandingWriteRequests = 1; |
| 609 | + params.maxWriteBufferCount = 3; |
| 610 | + |
| 611 | + ShardFollowNodeTask task = createShardFollowTask(params); |
| 612 | + startTask(task, 99, -1); |
| 613 | + |
| 614 | + task.coordinateReads(); |
| 615 | + assertThat(shardChangesRequests.size(), equalTo(2)); |
| 616 | + assertThat(shardChangesRequests.get(0)[0], equalTo(0L)); |
| 617 | + assertThat(shardChangesRequests.get(0)[1], equalTo(10L)); |
| 618 | + assertThat(shardChangesRequests.get(1)[0], equalTo(10L)); |
| 619 | + assertThat(shardChangesRequests.get(1)[1], equalTo(10L)); |
| 620 | + |
| 621 | + task.innerHandleReadResponse(0L, 9L, generateShardChangesResponse(0L, 5L, 0L, 0L, 1L, 99L)); |
| 622 | + assertThat(pendingBulkShardRequests, hasSize(1)); |
| 623 | + assertThat("continue the partial request", shardChangesRequests, hasSize(3)); |
| 624 | + assertThat(shardChangesRequests.get(2)[0], equalTo(6L)); |
| 625 | + assertThat(shardChangesRequests.get(2)[1], equalTo(4L)); |
| 626 | + assertThat(pendingBulkShardRequests, hasSize(1)); |
| 627 | + task.innerHandleReadResponse(10, 19L, generateShardChangesResponse(10L, 17L, 0L, 0L, 1L, 99L)); |
| 628 | + assertThat("do not continue partial reads as the buffer is full", shardChangesRequests, hasSize(3)); |
| 629 | + task.innerHandleReadResponse(6L, 9L, generateShardChangesResponse(6L, 8L, 0L, 0L, 1L, 99L)); |
| 630 | + assertThat("do not continue partial reads as the buffer is full", shardChangesRequests, hasSize(3)); |
| 631 | + pendingBulkShardRequests.remove().onResponse(new BulkShardOperationsResponse()); |
| 632 | + assertThat(pendingBulkShardRequests, hasSize(1)); |
| 633 | + |
| 634 | + assertThat("continue two partial requests as the buffer is empty after sending", shardChangesRequests, hasSize(5)); |
| 635 | + assertThat(shardChangesRequests.get(3)[0], equalTo(9L)); |
| 636 | + assertThat(shardChangesRequests.get(3)[1], equalTo(1L)); |
| 637 | + assertThat(shardChangesRequests.get(4)[0], equalTo(18L)); |
| 638 | + assertThat(shardChangesRequests.get(4)[1], equalTo(2L)); |
| 639 | + |
| 640 | + task.innerHandleReadResponse(18L, 19L, generateShardChangesResponse(18L, 19L, 0L, 0L, 1L, 99L)); |
| 641 | + assertThat("start new range as the buffer has empty slots", shardChangesRequests, hasSize(6)); |
| 642 | + assertThat(shardChangesRequests.get(5)[0], equalTo(20L)); |
| 643 | + assertThat(shardChangesRequests.get(5)[1], equalTo(10L)); |
| 644 | + |
| 645 | + task.innerHandleReadResponse(9L, 9L, generateShardChangesResponse(9L, 9L, 0L, 0L, 1L, 99L)); |
| 646 | + assertThat("do not start new range as the buffer is full", shardChangesRequests, hasSize(6)); |
| 647 | + pendingBulkShardRequests.remove().onResponse(new BulkShardOperationsResponse()); |
| 648 | + assertThat("start new range as the buffer is empty after sending", shardChangesRequests, hasSize(7)); |
| 649 | + assertThat(shardChangesRequests.get(6)[0], equalTo(30L)); |
| 650 | + assertThat(shardChangesRequests.get(6)[1], equalTo(10L)); |
| 651 | + } |
| 652 | + |
602 | 653 | public void testMappingUpdate() { |
603 | 654 | ShardFollowTaskParams params = new ShardFollowTaskParams(); |
604 | 655 | params.maxReadRequestOperationCount = 64; |
@@ -996,7 +1047,7 @@ public void testMaxWriteRequestSize() { |
996 | 1047 |
|
997 | 1048 | ShardChangesAction.Response response = generateShardChangesResponse(0, 63, 0L, 0L, 1L, 64L); |
998 | 1049 | // Also invokes coordinatesWrites() |
999 | | - task.innerHandleReadResponse(0L, 64L, response); |
| 1050 | + task.innerHandleReadResponse(0L, 63L, response); |
1000 | 1051 |
|
1001 | 1052 | assertThat(bulkShardOperationRequests.size(), equalTo(64)); |
1002 | 1053 | } |
@@ -1122,6 +1173,7 @@ private ShardFollowNodeTask createShardFollowTask(ShardFollowTaskParams params) |
1122 | 1173 | followerGlobalCheckpoints = new LinkedList<>(); |
1123 | 1174 | maxSeqNos = new LinkedList<>(); |
1124 | 1175 | responseSizes = new LinkedList<>(); |
| 1176 | + pendingBulkShardRequests = new LinkedList<>(); |
1125 | 1177 | return new ShardFollowNodeTask( |
1126 | 1178 | 1L, "type", ShardFollowTask.NAME, "description", null, Collections.emptyMap(), followTask, scheduler, System::nanoTime) { |
1127 | 1179 |
|
@@ -1185,6 +1237,8 @@ protected void innerSendBulkShardOperationsRequest( |
1185 | 1237 | response.setGlobalCheckpoint(followerGlobalCheckpoint); |
1186 | 1238 | response.setMaxSeqNo(followerGlobalCheckpoint); |
1187 | 1239 | handler.accept(response); |
| 1240 | + } else { |
| 1241 | + pendingBulkShardRequests.add(ActionListener.wrap(handler::accept, errorHandler)); |
1188 | 1242 | } |
1189 | 1243 | } |
1190 | 1244 |
|
|
0 commit comments