diff --git a/changelog/unreleased/SOLR-18248-refactor-list-api.yml b/changelog/unreleased/SOLR-18248-refactor-list-api.yml new file mode 100644 index 000000000000..bfbf28648ca1 --- /dev/null +++ b/changelog/unreleased/SOLR-18248-refactor-list-api.yml @@ -0,0 +1,7 @@ +title: Refactor Tasks API to use Nested Interfaces +type: updated +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/TasksApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/TasksApi.java index 3e46c1465c64..d1980f4e4f8d 100644 --- a/solr/api/src/java/org/apache/solr/client/api/endpoint/TasksApi.java +++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/TasksApi.java @@ -30,18 +30,23 @@ @Path(INDEX_PATH_PREFIX + "/tasks") public interface TasksApi { - @GET - @StoreApiParameters - @Operation( - summary = "Lists all the active tasks", - tags = {"tasks"}) - ListActiveTaskResponse listAllActiveTasks() throws Exception; + @Path("") + interface List { + @GET + @StoreApiParameters + @Operation( + summary = "Lists all the active tasks.", + tags = {"tasks"}) + ListActiveTaskResponse listAllActiveTasks() throws Exception; + } - @GET @Path("/{taskID}") - @StoreApiParameters - @Operation( - summary = "Status of a specific task", - tags = {"tasks"}) - TaskStatusResponse getTaskStatus(@PathParam("taskID") String taskID) throws Exception; + interface Status { + @GET + @StoreApiParameters + @Operation( + summary = "Status of a specific task.", + tags = {"tasks"}) + TaskStatusResponse getTaskStatus(@PathParam("taskID") String taskID) throws Exception; + } } diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/GetTaskStatus.java b/solr/core/src/java/org/apache/solr/handler/admin/api/GetTaskStatus.java new file mode 100644 index 000000000000..39e64eb68ca2 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/GetTaskStatus.java @@ -0,0 +1,53 @@ +/* + * 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 org.apache.solr.api.JerseyResource; +import org.apache.solr.client.api.endpoint.TasksApi; +import org.apache.solr.client.api.model.TaskStatusResponse; +import org.apache.solr.handler.component.ActiveTaskQuerySupport; +import org.apache.solr.jersey.PermissionName; +import org.apache.solr.request.SolrQueryRequest; + +public class GetTaskStatus extends JerseyResource implements TasksApi.Status { + + private final SolrQueryRequest solrQueryRequest; + + @Inject + public GetTaskStatus(SolrQueryRequest solrQueryRequest) { + this.solrQueryRequest = solrQueryRequest; + } + + @Override + @PermissionName(READ_PERM) + public TaskStatusResponse getTaskStatus(String taskID) throws Exception { + final TaskStatusResponse response = instantiateJerseyResponse(TaskStatusResponse.class); + + boolean isTaskActive = ActiveTaskQuerySupport.isTaskActive(solrQueryRequest, taskID); + + response.status = + (isTaskActive) + ? TaskStatusResponse.TaskStatus.ACTIVE + : TaskStatusResponse.TaskStatus.INACTIVE; + + return response; + } +} diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/ActiveTask.java b/solr/core/src/java/org/apache/solr/handler/admin/api/ListActiveTasks.java similarity index 79% rename from solr/core/src/java/org/apache/solr/handler/admin/api/ActiveTask.java rename to solr/core/src/java/org/apache/solr/handler/admin/api/ListActiveTasks.java index 6ed8fa001fdf..6717fd095fcc 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/ActiveTask.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/ListActiveTasks.java @@ -28,17 +28,16 @@ import org.apache.solr.client.api.endpoint.TasksApi; 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.handler.component.ActiveTaskQuerySupport; import org.apache.solr.jersey.PermissionName; import org.apache.solr.request.SolrQueryRequest; -public class ActiveTask extends JerseyResource implements TasksApi { +public class ListActiveTasks extends JerseyResource implements TasksApi.List { private final SolrQueryRequest solrQueryRequest; @Inject - public ActiveTask(SolrQueryRequest solrQueryRequest) { + public ListActiveTasks(SolrQueryRequest solrQueryRequest) { this.solrQueryRequest = solrQueryRequest; } @@ -50,21 +49,6 @@ public ListActiveTaskResponse listAllActiveTasks() throws Exception { return response; } - @Override - @PermissionName(READ_PERM) - public TaskStatusResponse getTaskStatus(String taskID) throws Exception { - final TaskStatusResponse response = instantiateJerseyResponse(TaskStatusResponse.class); - - boolean isTaskActive = ActiveTaskQuerySupport.isTaskActive(solrQueryRequest, taskID); - - response.status = - (isTaskActive) - ? TaskStatusResponse.TaskStatus.ACTIVE - : TaskStatusResponse.TaskStatus.INACTIVE; - - return response; - } - public static List getActiveTasksOnThisShard( SolrQueryRequest solrQueryRequest) { Iterator> iterator = diff --git a/solr/core/src/java/org/apache/solr/handler/component/ActiveTaskQuerySupport.java b/solr/core/src/java/org/apache/solr/handler/component/ActiveTaskQuerySupport.java index e1da0f6bb44f..6276b419451f 100644 --- a/solr/core/src/java/org/apache/solr/handler/component/ActiveTaskQuerySupport.java +++ b/solr/core/src/java/org/apache/solr/handler/component/ActiveTaskQuerySupport.java @@ -29,7 +29,7 @@ import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.util.NamedList; import org.apache.solr.core.CoreContainer; -import org.apache.solr.handler.admin.api.ActiveTask; +import org.apache.solr.handler.admin.api.ListActiveTasks; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.response.SolrQueryResponse; @@ -55,9 +55,9 @@ private static TaskQueryResult execute(SolrQueryRequest req, String taskId) thro private static TaskQueryResult localResult(SolrQueryRequest req, String taskId) { if (taskId != null) { - return new TaskQueryResult(List.of(), ActiveTask.isTaskActiveOnThisShard(req, taskId)); + return new TaskQueryResult(List.of(), ListActiveTasks.isTaskActiveOnThisShard(req, taskId)); } - return new TaskQueryResult(ActiveTask.getActiveTasksOnThisShard(req), false); + return new TaskQueryResult(ListActiveTasks.getActiveTasksOnThisShard(req), false); } private static TaskQueryResult distributedResult(SolrQueryRequest req, String taskId) 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 810e66d8957d..bb6fa6c2523e 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 @@ -26,7 +26,8 @@ import org.apache.solr.common.params.ShardParams; import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.SimpleOrderedMap; -import org.apache.solr.handler.admin.api.ActiveTask; +import org.apache.solr.handler.admin.api.GetTaskStatus; +import org.apache.solr.handler.admin.api.ListActiveTasks; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.request.SolrRequestHandler; import org.apache.solr.response.SolrQueryResponse; @@ -102,6 +103,6 @@ public Collection getApis() { @Override public Collection> getJerseyResources() { - return List.of(ActiveTask.class); + return List.of(ListActiveTasks.class, GetTaskStatus.class); } } diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/GetTaskStatusTest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/GetTaskStatusTest.java new file mode 100644 index 000000000000..acc4fa1d1c7b --- /dev/null +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/GetTaskStatusTest.java @@ -0,0 +1,73 @@ +/* + * 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 org.apache.solr.SolrTestCaseJ4; +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 GetTaskStatusTest extends SolrTestCaseJ4 { + + private SolrQueryRequest mockQueryRequest; + private SolrCore solrCore; + private CancellableQueryTracker cancellableQueryTracker; + + private GetTaskStatus getTaskStatus; + + @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); + + getTaskStatus = new GetTaskStatus(mockQueryRequest); + } + + @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 = getTaskStatus.getTaskStatus("taskID_running"); + assertEquals(TaskStatusResponse.TaskStatus.ACTIVE, responseRunningTask.status); + assertNull(responseRunningTask.error); + + TaskStatusResponse responseStoppedTask = getTaskStatus.getTaskStatus("taskID_stopped"); + assertEquals(TaskStatusResponse.TaskStatus.INACTIVE, responseStoppedTask.status); + assertNull(responseStoppedTask.error); + } +} diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/ActiveTaskTest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/ListActiveTasksTest.java similarity index 70% rename from solr/core/src/test/org/apache/solr/handler/admin/api/ActiveTaskTest.java rename to solr/core/src/test/org/apache/solr/handler/admin/api/ListActiveTasksTest.java index 1ab1e2bc489f..113f9dcb82a2 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/ActiveTaskTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/ListActiveTasksTest.java @@ -25,7 +25,6 @@ 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; @@ -33,13 +32,13 @@ import org.junit.BeforeClass; import org.junit.Test; -public class ActiveTaskTest extends SolrTestCaseJ4 { +public class ListActiveTasksTest extends SolrTestCaseJ4 { private SolrQueryRequest mockQueryRequest; private SolrCore solrCore; private CancellableQueryTracker cancellableQueryTracker; - private ActiveTask activeTask; + private ListActiveTasks listActiveTasks; @BeforeClass public static void ensureWorkingMockito() { @@ -55,7 +54,7 @@ public void setUp() throws Exception { solrCore = mock(SolrCore.class); cancellableQueryTracker = mock(CancellableQueryTracker.class); - activeTask = new ActiveTask(mockQueryRequest); + listActiveTasks = new ListActiveTasks(mockQueryRequest); } @Test @@ -70,7 +69,7 @@ public void testGetActiveTasks() throws Exception { when(solrCore.getCancellableQueryTracker()).thenReturn(cancellableQueryTracker); when(cancellableQueryTracker.getActiveQueriesGenerated()).thenReturn(mockIterator); - ListActiveTaskResponse response = activeTask.listAllActiveTasks(); + ListActiveTaskResponse response = listActiveTasks.listAllActiveTasks(); assertNotNull(response.tasks); assertEquals(2, response.tasks.size()); @@ -80,21 +79,4 @@ public void testGetActiveTasks() throws Exception { 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 = activeTask.getTaskStatus("taskID_running"); - assertEquals(TaskStatusResponse.TaskStatus.ACTIVE, responseRunningTask.status); - assertNull(responseRunningTask.error); - - TaskStatusResponse responseStoppedTask = activeTask.getTaskStatus("taskID_stopped"); - assertEquals(TaskStatusResponse.TaskStatus.INACTIVE, responseStoppedTask.status); - assertNull(responseStoppedTask.error); - } }