|
8 | 8 | package org.elasticsearch.xpack.esql.action; |
9 | 9 |
|
10 | 10 | import org.elasticsearch.action.index.IndexRequestBuilder; |
| 11 | +import org.elasticsearch.cluster.ClusterState; |
| 12 | +import org.elasticsearch.cluster.metadata.IndexMetadata; |
| 13 | +import org.elasticsearch.cluster.service.ClusterService; |
11 | 14 | import org.elasticsearch.index.IndexService; |
12 | 15 | import org.elasticsearch.index.shard.IndexShard; |
13 | 16 | import org.elasticsearch.indices.IndicesService; |
|
20 | 23 | import java.util.ArrayList; |
21 | 24 | import java.util.Collection; |
22 | 25 | import java.util.List; |
| 26 | +import java.util.concurrent.CountDownLatch; |
| 27 | +import java.util.concurrent.TimeUnit; |
23 | 28 | import java.util.concurrent.atomic.AtomicBoolean; |
24 | 29 |
|
25 | 30 | import static org.elasticsearch.index.shard.IndexShardTestCase.closeShardNoCheck; |
26 | 31 | import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; |
27 | 32 | import static org.hamcrest.Matchers.equalTo; |
| 33 | +import static org.hamcrest.Matchers.not; |
28 | 34 |
|
29 | 35 | public class EsqlRetryIT extends AbstractEsqlIntegTestCase { |
30 | 36 |
|
@@ -59,6 +65,37 @@ public void testRetryOnShardFailures() throws Exception { |
59 | 65 | } |
60 | 66 | } |
61 | 67 |
|
| 68 | + public void testQueryWhileDeletingIndices() { |
| 69 | + populateIndices(); |
| 70 | + CountDownLatch waitForDeletion = new CountDownLatch(1); |
| 71 | + try { |
| 72 | + final AtomicBoolean deleted = new AtomicBoolean(); |
| 73 | + for (String node : internalCluster().getNodeNames()) { |
| 74 | + MockTransportService.getInstance(node) |
| 75 | + .addRequestHandlingBehavior(ComputeService.DATA_ACTION_NAME, (handler, request, channel, task) -> { |
| 76 | + if (deleted.compareAndSet(false, true)) { |
| 77 | + deleteIndexCompletely("log-index-2"); |
| 78 | + waitForDeletion.countDown(); |
| 79 | + } else { |
| 80 | + assertTrue(waitForDeletion.await(10, TimeUnit.SECONDS)); |
| 81 | + } |
| 82 | + handler.messageReceived(request, channel, task); |
| 83 | + }); |
| 84 | + } |
| 85 | + EsqlQueryRequest request = new EsqlQueryRequest(); |
| 86 | + request.query("FROM log-* | STATS COUNT(timestamp) | LIMIT 1"); |
| 87 | + request.allowPartialResults(true); |
| 88 | + try (var resp = run(request)) { |
| 89 | + assertTrue(resp.isPartial()); |
| 90 | + assertThat(EsqlTestUtils.getValuesList(resp).getFirst().getFirst(), equalTo(4L)); |
| 91 | + } |
| 92 | + } finally { |
| 93 | + for (String node : internalCluster().getNodeNames()) { |
| 94 | + MockTransportService.getInstance(node).clearAllRules(); |
| 95 | + } |
| 96 | + } |
| 97 | + } |
| 98 | + |
62 | 99 | private void populateIndices() { |
63 | 100 | internalCluster().ensureAtLeastNumDataNodes(2); |
64 | 101 | assertAcked(prepareCreate("log-index-1").setSettings(indexSettings(between(1, 3), 1)).setMapping("timestamp", "type=date")); |
@@ -88,4 +125,36 @@ private void closeOrFailShards(String nodeName) throws Exception { |
88 | 125 | } |
89 | 126 | } |
90 | 127 | } |
| 128 | + |
| 129 | + /** |
| 130 | + * Deletes the given index and ensures it is completely removed from the cluster state and from all nodes |
| 131 | + */ |
| 132 | + private void deleteIndexCompletely(String indexName) throws Exception { |
| 133 | + assertAcked(indicesAdmin().prepareDelete(indexName)); |
| 134 | + String[] nodeNames = internalCluster().getNodeNames(); |
| 135 | + assertBusy(() -> { |
| 136 | + for (String nodeName : nodeNames) { |
| 137 | + ClusterState clusterState = internalCluster().getInstance(ClusterService.class, nodeName).state(); |
| 138 | + for (IndexMetadata imd : clusterState.metadata().indicesAllProjects()) { |
| 139 | + assertThat( |
| 140 | + "Index [" + indexName + "] still exists on the cluster state on [" + nodeName + "]", |
| 141 | + imd.getIndex().getName(), |
| 142 | + not(equalTo(indexName)) |
| 143 | + ); |
| 144 | + } |
| 145 | + } |
| 146 | + for (String nodeName : nodeNames) { |
| 147 | + final IndicesService indicesService = internalCluster().getInstance(IndicesService.class, nodeName); |
| 148 | + for (IndexService indexService : indicesService) { |
| 149 | + for (IndexShard indexShard : indexService) { |
| 150 | + assertThat( |
| 151 | + "Index [" + indexName + "] still exists on node [" + nodeName + "]", |
| 152 | + indexShard.shardId().getIndexName(), |
| 153 | + not(equalTo(indexName)) |
| 154 | + ); |
| 155 | + } |
| 156 | + } |
| 157 | + } |
| 158 | + }); |
| 159 | + } |
91 | 160 | } |
0 commit comments