|
10 | 10 | import org.elasticsearch.ResourceNotFoundException;
|
11 | 11 | import org.elasticsearch.action.support.master.AcknowledgedResponse;
|
12 | 12 | import org.elasticsearch.common.settings.Settings;
|
| 13 | +import org.elasticsearch.compute.operator.DriverTaskRunner; |
13 | 14 | import org.elasticsearch.compute.operator.exchange.ExchangeService;
|
14 | 15 | import org.elasticsearch.core.TimeValue;
|
15 | 16 | import org.elasticsearch.plugins.Plugin;
|
| 17 | +import org.elasticsearch.tasks.TaskCancelledException; |
16 | 18 | import org.elasticsearch.tasks.TaskInfo;
|
17 | 19 | import org.elasticsearch.xpack.core.LocalStateCompositeXPackPlugin;
|
18 | 20 | import org.elasticsearch.xpack.core.async.DeleteAsyncResultRequest;
|
|
34 | 36 | import static org.elasticsearch.test.hamcrest.OptionalMatchers.isEmpty;
|
35 | 37 | import static org.elasticsearch.test.hamcrest.OptionalMatchers.isPresent;
|
36 | 38 | import static org.elasticsearch.xpack.esql.EsqlTestUtils.getValuesList;
|
| 39 | +import static org.hamcrest.Matchers.empty; |
37 | 40 | import static org.hamcrest.Matchers.equalTo;
|
| 41 | +import static org.hamcrest.Matchers.greaterThanOrEqualTo; |
38 | 42 | import static org.hamcrest.Matchers.is;
|
| 43 | +import static org.hamcrest.Matchers.not; |
39 | 44 | import static org.hamcrest.Matchers.notNullValue;
|
40 | 45 |
|
41 | 46 | /**
|
@@ -112,6 +117,59 @@ public void testBasicAsyncExecution() throws Exception {
|
112 | 117 | }
|
113 | 118 | }
|
114 | 119 |
|
| 120 | + public void testGetAsyncWhileQueryTaskIsBeingCancelled() throws Exception { |
| 121 | + try (var initialResponse = sendAsyncQuery()) { |
| 122 | + assertThat(initialResponse.asyncExecutionId(), isPresent()); |
| 123 | + assertThat(initialResponse.isRunning(), is(true)); |
| 124 | + String id = initialResponse.asyncExecutionId().get(); |
| 125 | + // ensure we have started Lucene operators |
| 126 | + assertBusy(() -> { |
| 127 | + var tasks = client().admin() |
| 128 | + .cluster() |
| 129 | + .prepareListTasks() |
| 130 | + .setActions(DriverTaskRunner.ACTION_NAME) |
| 131 | + .setDetailed(true) |
| 132 | + .get() |
| 133 | + .getTasks() |
| 134 | + .stream() |
| 135 | + .filter(t -> t.description().contains("_LuceneSourceOperator")) |
| 136 | + .toList(); |
| 137 | + assertThat(tasks.size(), greaterThanOrEqualTo(1)); |
| 138 | + }); |
| 139 | + client().admin().cluster().prepareCancelTasks().setActions(EsqlQueryAction.NAME + "[a]").get(); |
| 140 | + assertBusy(() -> { |
| 141 | + List<TaskInfo> tasks = getEsqlQueryTasks().stream().filter(TaskInfo::cancelled).toList(); |
| 142 | + assertThat(tasks, not(empty())); |
| 143 | + }); |
| 144 | + // get the result while the query is being cancelled |
| 145 | + { |
| 146 | + var getResultsRequest = new GetAsyncResultRequest(id); |
| 147 | + getResultsRequest.setWaitForCompletionTimeout(timeValueMillis(10)); |
| 148 | + getResultsRequest.setKeepAlive(randomKeepAlive()); |
| 149 | + var future = client().execute(EsqlAsyncGetResultAction.INSTANCE, getResultsRequest); |
| 150 | + try (var resp = future.get()) { |
| 151 | + assertThat(initialResponse.asyncExecutionId(), isPresent()); |
| 152 | + assertThat(resp.asyncExecutionId().get(), equalTo(id)); |
| 153 | + assertThat(resp.isRunning(), is(true)); |
| 154 | + } |
| 155 | + } |
| 156 | + // release the permits to allow the query to proceed |
| 157 | + scriptPermits.release(numberOfDocs()); |
| 158 | + // get the result after the cancellation is done |
| 159 | + { |
| 160 | + var getResultsRequest = new GetAsyncResultRequest(id); |
| 161 | + getResultsRequest.setWaitForCompletionTimeout(timeValueSeconds(10)); |
| 162 | + getResultsRequest.setKeepAlive(randomKeepAlive()); |
| 163 | + var future = client().execute(EsqlAsyncGetResultAction.INSTANCE, getResultsRequest); |
| 164 | + TaskCancelledException error = expectThrows(TaskCancelledException.class, future::actionGet); |
| 165 | + assertThat(error.getMessage(), equalTo("by user request")); |
| 166 | + } |
| 167 | + assertTrue(deleteAsyncId(id).isAcknowledged()); |
| 168 | + } finally { |
| 169 | + scriptPermits.drainPermits(); |
| 170 | + } |
| 171 | + } |
| 172 | + |
115 | 173 | public void testAsyncCancellation() throws Exception {
|
116 | 174 | try (var initialResponse = sendAsyncQuery()) {
|
117 | 175 | assertThat(initialResponse.asyncExecutionId(), isPresent());
|
|
0 commit comments