diff --git a/changelog/unreleased/SOLR-18248-list-tasks.yml b/changelog/unreleased/SOLR-18248-list-tasks.yml new file mode 100644 index 000000000000..5e8df2c0b414 --- /dev/null +++ b/changelog/unreleased/SOLR-18248-list-tasks.yml @@ -0,0 +1,7 @@ +title: Migrated ListTasks API & TaskStatus API from homegrown @EndPoint to JAX-RS +type: added +authors: + - name: Jalaz Kumar +links: + - name: SOLR-18248 + url: https://issues.apache.org/jira/browse/SOLR-18248 diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/ListActiveTasksApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/ListActiveTasksApi.java new file mode 100644 index 000000000000..b42a8cb38f1c --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/ListActiveTasksApi.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.client.api.endpoint; + +import static org.apache.solr.client.api.util.Constants.INDEX_PATH_PREFIX; + +import io.swagger.v3.oas.annotations.Operation; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import org.apache.solr.client.api.model.ListActiveTaskResponse; +import org.apache.solr.client.api.model.TaskStatusResponse; +import org.apache.solr.client.api.util.StoreApiParameters; + +@Path(INDEX_PATH_PREFIX + "/tasks/list") +public interface ListActiveTasksApi { + + // Handles: .../tasks/list (Lists all) + @GET + @StoreApiParameters + @Operation( + summary = "Lists all the currently running tasks", + tags = {"tasks"}) + ListActiveTaskResponse listAllActiveTasks() throws Exception; + + // Handles: .../tasks/list/slow-task-id (Lists specific) + @GET + @Path("/{taskUUID}") + @StoreApiParameters + @Operation( + summary = "Status of a specific taskUUID passed as pathParam", + tags = {"tasks"}) + TaskStatusResponse getTaskStatus(@PathParam("taskUUID") String taskUUID) throws Exception; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/ActiveTaskDetails.java b/solr/api/src/java/org/apache/solr/client/api/model/ActiveTaskDetails.java new file mode 100644 index 000000000000..874267024f58 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/ActiveTaskDetails.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.client.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class ActiveTaskDetails { + + public ActiveTaskDetails() {} + + public ActiveTaskDetails(String taskUUID, String taskQuery) { + this.taskUUID = taskUUID; + this.taskQuery = taskQuery; + } + + @JsonProperty public String taskUUID; + @JsonProperty public String taskQuery; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/ListActiveTaskResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/ListActiveTaskResponse.java new file mode 100644 index 000000000000..f74ec9096077 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/ListActiveTaskResponse.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.client.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; + +public class ListActiveTaskResponse extends SolrJerseyResponse { + @JsonProperty public List taskList; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/TaskStatusResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/TaskStatusResponse.java new file mode 100644 index 000000000000..6cae72670d7c --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/TaskStatusResponse.java @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.client.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class TaskStatusResponse extends SolrJerseyResponse { + @JsonProperty public String taskStatus; +} diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/ListActiveTasks.java b/solr/core/src/java/org/apache/solr/handler/admin/api/ListActiveTasks.java new file mode 100644 index 000000000000..ea3fd00a4426 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/ListActiveTasks.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.handler.admin.api; + +import static org.apache.solr.security.PermissionNameProvider.Name.READ_PERM; + +import jakarta.inject.Inject; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import org.apache.solr.api.JerseyResource; +import org.apache.solr.client.api.endpoint.ListActiveTasksApi; +import org.apache.solr.client.api.model.ActiveTaskDetails; +import org.apache.solr.client.api.model.ListActiveTaskResponse; +import org.apache.solr.client.api.model.TaskStatusResponse; +import org.apache.solr.jersey.PermissionName; +import org.apache.solr.request.SolrQueryRequest; + +public class ListActiveTasks extends JerseyResource implements ListActiveTasksApi { + + private final SolrQueryRequest solrQueryRequest; + + @Inject + public ListActiveTasks(SolrQueryRequest solrQueryRequest) { + this.solrQueryRequest = solrQueryRequest; + } + + @Override + @PermissionName(READ_PERM) + public ListActiveTaskResponse listAllActiveTasks() throws Exception { + final ListActiveTaskResponse response = instantiateJerseyResponse(ListActiveTaskResponse.class); + + response.taskList = extractActiveTaskLists(); + + return response; + } + + @Override + @PermissionName(READ_PERM) + public TaskStatusResponse getTaskStatus(String taskUUID) throws Exception { + final TaskStatusResponse response = instantiateJerseyResponse(TaskStatusResponse.class); + + boolean isTaskActive = + solrQueryRequest.getCore().getCancellableQueryTracker().isQueryIdActive(taskUUID); + if (isTaskActive) { + response.taskStatus = "id: " + taskUUID + ", status: active"; + } else { + response.taskStatus = "id: " + taskUUID + ", status: inactive"; + } + + return response; + } + + private List extractActiveTaskLists() { + Iterator> iterator = + solrQueryRequest.getCore().getCancellableQueryTracker().getActiveQueriesGenerated(); + + List activeTaskDetails = new ArrayList<>(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + activeTaskDetails.add(new ActiveTaskDetails(entry.getKey(), entry.getValue())); + } + + return activeTaskDetails; + } +} diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/ListActiveTasksAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/ListActiveTasksAPI.java deleted file mode 100644 index fba3d9d26f3f..000000000000 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/ListActiveTasksAPI.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.solr.handler.admin.api; - -import static org.apache.solr.client.solrj.SolrRequest.METHOD.GET; - -import org.apache.solr.api.EndPoint; -import org.apache.solr.handler.component.ActiveTasksListHandler; -import org.apache.solr.request.SolrQueryRequest; -import org.apache.solr.response.SolrQueryResponse; -import org.apache.solr.security.PermissionNameProvider; - -/** - * V2 API for listing any currently running "tasks". - * - *

This API (GET /v2/collections/collectionName/tasks/list) is analogous to the v1 - * /solr/collectionName/tasks/list API. - */ -public class ListActiveTasksAPI { - private final ActiveTasksListHandler listTaskHandler; - - public ListActiveTasksAPI(ActiveTasksListHandler listTaskHandler) { - this.listTaskHandler = listTaskHandler; - } - - @EndPoint( - path = {"/tasks/list"}, - method = GET, - permission = PermissionNameProvider.Name.READ_PERM) - public void listActiveTasks(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception { - listTaskHandler.handleRequestBody(req, rsp); - } -} diff --git a/solr/core/src/java/org/apache/solr/handler/component/ActiveTasksListComponent.java b/solr/core/src/java/org/apache/solr/handler/component/ActiveTasksListComponent.java deleted file mode 100644 index ce8a31335c2f..000000000000 --- a/solr/core/src/java/org/apache/solr/handler/component/ActiveTasksListComponent.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.solr.handler.component; - -import java.io.IOException; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; -import org.apache.solr.common.MapWriter; -import org.apache.solr.common.util.NamedList; - -/** List the active tasks that can be cancelled */ -public class ActiveTasksListComponent extends SearchComponent { - public static final String COMPONENT_NAME = "activetaskslist"; - - private boolean shouldProcess; - - @Override - public void prepare(ResponseBuilder rb) throws IOException { - if (rb.isTaskListRequest()) { - shouldProcess = true; - } - } - - @Override - public void process(ResponseBuilder rb) { - if (!shouldProcess) { - return; - } - - if (rb.getTaskStatusCheckUUID() != null) { - boolean isActiveOnThisShard = - rb.req - .getCore() - .getCancellableQueryTracker() - .isQueryIdActive(rb.getTaskStatusCheckUUID()); - - rb.rsp.add("taskStatus", isActiveOnThisShard); - return; - } - - rb.rsp.add( - "taskList", - (MapWriter) - ew -> { - Iterator> iterator = - rb.req.getCore().getCancellableQueryTracker().getActiveQueriesGenerated(); - - while (iterator.hasNext()) { - Map.Entry entry = iterator.next(); - ew.put(entry.getKey(), entry.getValue()); - } - }); - } - - @Override - @SuppressWarnings("unchecked") - public void handleResponses(ResponseBuilder rb, ShardRequest sreq) { - if (!shouldProcess) { - return; - } - - NamedList resultList = new NamedList<>(); - - for (ShardResponse r : sreq.responses) { - - if (rb.getTaskStatusCheckUUID() != null) { - boolean isTaskActiveOnShard = r.getSolrResponse().getResponse().getBooleanArg("taskStatus"); - - if (isTaskActiveOnShard) { - rb.rsp - .getValues() - .add("taskStatus", "id:" + rb.getTaskStatusCheckUUID() + ", status: active"); - return; - } else { - continue; - } - } - - LinkedHashMap result = - (LinkedHashMap) r.getSolrResponse().getResponse().get("taskList"); - - Iterator> iterator = result.entrySet().iterator(); - - while (iterator.hasNext()) { - Map.Entry entry = iterator.next(); - - resultList.add(entry.getKey(), entry.getValue()); - } - } - - if (rb.getTaskStatusCheckUUID() != null) { - // We got here with the specific taskID check being specified -- this means that the taskID - // was not found in active tasks on any shard - rb.rsp - .getValues() - .add("taskStatus", "id:" + rb.getTaskStatusCheckUUID() + ", status: inactive"); - return; - } - - rb.rsp.getValues().add("taskList", resultList); - } - - @Override - public String getDescription() { - return "Responsible for listing all active cancellable tasks and also supports checking the status of " - + "a particular task"; - } - - @Override - public Category getCategory() { - return Category.OTHER; - } -} diff --git a/solr/core/src/java/org/apache/solr/handler/component/ActiveTasksListHandler.java b/solr/core/src/java/org/apache/solr/handler/component/ActiveTasksListHandler.java index f1ce12cd9378..4f367aad1a0d 100644 --- a/solr/core/src/java/org/apache/solr/handler/component/ActiveTasksListHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/component/ActiveTasksListHandler.java @@ -19,49 +19,52 @@ import static org.apache.solr.common.params.CommonParams.TASK_CHECK_UUID; import java.util.Collection; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import org.apache.solr.api.AnnotatedApi; import org.apache.solr.api.Api; -import org.apache.solr.handler.admin.api.ListActiveTasksAPI; +import org.apache.solr.api.JerseyResource; +import org.apache.solr.client.api.model.ActiveTaskDetails; +import org.apache.solr.common.util.NamedList; +import org.apache.solr.handler.admin.api.ListActiveTasks; +import org.apache.solr.handler.api.V2ApiUtils; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.request.SolrRequestHandler; import org.apache.solr.response.SolrQueryResponse; import org.apache.solr.security.AuthorizationContext; import org.apache.solr.security.PermissionNameProvider; -/** Handles request for listing all active cancellable tasks */ +/** + * Handles request for listing all active cancellable tasks All active tasks logic lives in the v2 + * {@link ListActiveTasks}; this handler is a thin v1 bridge that extracts request parameters and + * delegates. + */ public class ActiveTasksListHandler extends TaskManagementHandler { // This can be a parent level member but we keep it here to allow future handlers to have // a custom list of components - private List components; @Override public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception { - Map extraParams = null; - ResponseBuilder rb = buildResponseBuilder(req, rsp, getComponentsList()); - - rb.setIsTaskListRequest(true); - String taskStatusCheckUUID = req.getParams().get(TASK_CHECK_UUID, null); if (taskStatusCheckUUID != null) { - if (rb.isDistrib) { - extraParams = new HashMap<>(); - - extraParams.put(TASK_CHECK_UUID, taskStatusCheckUUID); + V2ApiUtils.squashIntoSolrResponseWithoutHeader( + rsp, new ListActiveTasks(req).getTaskStatus(taskStatusCheckUUID)); + } else { + NamedList tasks = new NamedList<>(); + List taskList = new ListActiveTasks(req).listAllActiveTasks().taskList; + if (taskList != null) { + for (ActiveTaskDetails task : taskList) { + tasks.add(task.taskUUID, task.taskQuery); + } } - - rb.setTaskStatusCheckUUID(taskStatusCheckUUID); + rsp.add("taskList", tasks); } - - processRequest(req, rb, extraParams); } + // ////////////////////// SolrInfoMBeans methods ////////////////////// + @Override public String getDescription() { - return "activetaskslist"; + return "Active Tasks List"; } @Override @@ -79,7 +82,6 @@ public SolrRequestHandler getSubHandler(String path) { if (path.startsWith("/tasks/list")) { return this; } - return null; } @@ -90,14 +92,11 @@ public Boolean registerV2() { @Override public Collection getApis() { - return AnnotatedApi.getApis(new ListActiveTasksAPI(this)); + return List.of(); } - private List getComponentsList() { - if (components == null) { - components = buildComponentsList(); - } - - return components; + @Override + public Collection> getJerseyResources() { + return List.of(ListActiveTasks.class); } } diff --git a/solr/core/src/java/org/apache/solr/handler/component/TaskManagementHandler.java b/solr/core/src/java/org/apache/solr/handler/component/TaskManagementHandler.java index afb7a05c5868..3e9c5ec21160 100644 --- a/solr/core/src/java/org/apache/solr/handler/component/TaskManagementHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/component/TaskManagementHandler.java @@ -115,9 +115,6 @@ public static List buildComponentsList() { QueryCancellationComponent component = new QueryCancellationComponent(); components.add(component); - ActiveTasksListComponent activeTasksListComponent = new ActiveTasksListComponent(); - components.add(activeTasksListComponent); - return components; } diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/ListActiveTasksTest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/ListActiveTasksTest.java new file mode 100644 index 000000000000..7fb8114e0726 --- /dev/null +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/ListActiveTasksTest.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.handler.admin.api; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import org.apache.solr.SolrTestCaseJ4; +import org.apache.solr.client.api.model.ListActiveTaskResponse; +import org.apache.solr.client.api.model.TaskStatusResponse; +import org.apache.solr.core.CancellableQueryTracker; +import org.apache.solr.core.SolrCore; +import org.apache.solr.request.SolrQueryRequest; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +public class ListActiveTasksTest extends SolrTestCaseJ4 { + + private SolrQueryRequest mockQueryRequest; + private SolrCore solrCore; + private CancellableQueryTracker cancellableQueryTracker; + + private ListActiveTasks listActiveTasks; + + @BeforeClass + public static void ensureWorkingMockito() { + assumeWorkingMockito(); + } + + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + + mockQueryRequest = mock(SolrQueryRequest.class); + solrCore = mock(SolrCore.class); + cancellableQueryTracker = mock(CancellableQueryTracker.class); + + listActiveTasks = new ListActiveTasks(mockQueryRequest); + } + + @Test + public void testGetActiveTasks() throws Exception { + + Map myMap = new LinkedHashMap<>(); + myMap.put("taskID1", "/search?q=h&gf=text-1"); + myMap.put("taskID2", "/search?q=h&gf=text-2"); + Iterator> mockIterator = myMap.entrySet().iterator(); + + when(mockQueryRequest.getCore()).thenReturn(solrCore); + when(solrCore.getCancellableQueryTracker()).thenReturn(cancellableQueryTracker); + when(cancellableQueryTracker.getActiveQueriesGenerated()).thenReturn(mockIterator); + + ListActiveTaskResponse response = listActiveTasks.listAllActiveTasks(); + assertNotNull(response.taskList); + + assertEquals(2, response.taskList.size()); + + assertEquals("taskID1", response.taskList.get(0).taskUUID); + assertEquals("/search?q=h&gf=text-1", response.taskList.get(0).taskQuery); + + assertNull(response.error); + } + + @Test + public void testGetTaskStatus() throws Exception { + + when(mockQueryRequest.getCore()).thenReturn(solrCore); + when(solrCore.getCancellableQueryTracker()).thenReturn(cancellableQueryTracker); + when(cancellableQueryTracker.isQueryIdActive("taskID_running")).thenReturn(true); + when(cancellableQueryTracker.isQueryIdActive("taskID_stopped")).thenReturn(false); + + TaskStatusResponse responseRunningTask = listActiveTasks.getTaskStatus("taskID_running"); + assertTrue(responseRunningTask.taskStatus.contains("active")); + assertNull(responseRunningTask.error); + + TaskStatusResponse responseStoppedTask = listActiveTasks.getTaskStatus("taskID_stopped"); + assertTrue(responseStoppedTask.taskStatus.contains("inactive")); + assertNull(responseStoppedTask.error); + } +} diff --git a/solr/core/src/test/org/apache/solr/search/TestTaskManagement.java b/solr/core/src/test/org/apache/solr/search/TestTaskManagement.java index 13c98d87aceb..ed6a0bb121c0 100644 --- a/solr/core/src/test/org/apache/solr/search/TestTaskManagement.java +++ b/solr/core/src/test/org/apache/solr/search/TestTaskManagement.java @@ -213,6 +213,46 @@ public void testCheckSpecificQueryStatus() throws Exception { assertTrue(result.contains("inactive")); } + @Test + public void testCheckSpecificQueryStatus_Active() throws Exception { + for (int i = 0; i < 10; i++) { + executeQueryAsync(Integer.toString(i)); + } + + ModifiableSolrParams params = new ModifiableSolrParams(); + params.set("taskUUID", "5"); + + var request = + new GenericSolrRequest( + SolrRequest.METHOD.GET, "/tasks/list", SolrRequest.SolrRequestType.ADMIN, params) + .setRequiresCollection(true); + NamedList queryResponse = cluster.getSolrClient(COLLECTION_NAME).request(request); + + String result = (String) queryResponse.get("taskStatus"); + + assertTrue(result.contains("active")); + } + + @Test + public void testCheckSpecificQueryStatus_Inactive() throws Exception { + for (int i = 0; i < 10; i++) { + executeQueryAsync(Integer.toString(i)); + } + + ModifiableSolrParams params = new ModifiableSolrParams(); + params.set("taskUUID", "15"); + + var request = + new GenericSolrRequest( + SolrRequest.METHOD.GET, "/tasks/list", SolrRequest.SolrRequestType.ADMIN, params) + .setRequiresCollection(true); + NamedList queryResponse = cluster.getSolrClient(COLLECTION_NAME).request(request); + + String result = (String) queryResponse.get("taskStatus"); + + assertTrue(result.contains("inactive")); + } + private CompletableFuture cancelQuery( final String queryID, Set cancelledQueryIdsSet, Set notFoundQueryIdSet) { return CompletableFuture.runAsync(