From acccb1650f2263603364d652c08b75a980cc7662 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 16 May 2026 03:35:42 +0530 Subject: [PATCH 01/70] initial changes --- .../api/endpoint/ListActiveTasksApi.java | 20 +++++++++++++++++++ .../client/api/model/ActiveTaskDetails.java | 5 +++++ .../api/model/ListActiveTaskResponse.java | 9 +++++++++ 3 files changed, 34 insertions(+) create mode 100644 solr/api/src/java/org/apache/solr/client/api/endpoint/ListActiveTasksApi.java create mode 100644 solr/api/src/java/org/apache/solr/client/api/model/ActiveTaskDetails.java create mode 100644 solr/api/src/java/org/apache/solr/client/api/model/ListActiveTaskResponse.java 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..1dc06f44d76a --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/ListActiveTasksApi.java @@ -0,0 +1,20 @@ +package org.apache.solr.client.api.endpoint; + +import io.swagger.v3.oas.annotations.Operation; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.QueryParam; +import org.apache.solr.client.api.model.ListActiveTaskResponse; +import org.apache.solr.client.api.util.StoreApiParameters; + +import static org.apache.solr.client.api.util.Constants.INDEX_PATH_PREFIX; + +@Path(INDEX_PATH_PREFIX + "/tasks/list") +public interface ListActiveTasksApi { + @GET + @StoreApiParameters + @Operation( + summary = "Lists all the currently running tasks", + tags = {"tasks"}) + ListActiveTaskResponse listActiveTasks(@QueryParam("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..28553667b33b --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/ActiveTaskDetails.java @@ -0,0 +1,5 @@ +package org.apache.solr.client.api.model; + +public class ActiveTaskDetails { + +} 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..826039cd8060 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/ListActiveTaskResponse.java @@ -0,0 +1,9 @@ +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; +} From e4260140cebb3d841de26378c2d9d530539c1c04 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 16 May 2026 14:48:01 +0530 Subject: [PATCH 02/70] testing --- .../api/endpoint/ListActiveTasksApi.java | 7 +++- .../client/api/model/ActiveTaskDetails.java | 5 --- .../api/model/ListActiveTaskResponse.java | 3 +- .../handler/admin/api/ListActiveTasks.java | 40 +++++++++++++++++++ .../component/TaskManagementHandler.java | 9 +++++ 5 files changed, 56 insertions(+), 8 deletions(-) delete mode 100644 solr/api/src/java/org/apache/solr/client/api/model/ActiveTaskDetails.java create mode 100644 solr/core/src/java/org/apache/solr/handler/admin/api/ListActiveTasks.java 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 index 1dc06f44d76a..b76775456002 100644 --- 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 @@ -1,20 +1,23 @@ package org.apache.solr.client.api.endpoint; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; import jakarta.ws.rs.QueryParam; import org.apache.solr.client.api.model.ListActiveTaskResponse; import org.apache.solr.client.api.util.StoreApiParameters; import static org.apache.solr.client.api.util.Constants.INDEX_PATH_PREFIX; -@Path(INDEX_PATH_PREFIX + "/tasks/list") +@Path(INDEX_PATH_PREFIX + "/tasks/listjalaz") public interface ListActiveTasksApi { @GET @StoreApiParameters @Operation( summary = "Lists all the currently running tasks", tags = {"tasks"}) - ListActiveTaskResponse listActiveTasks(@QueryParam("taskUUID") String taskUUID) throws Exception; + ListActiveTaskResponse listActiveTasks( + @QueryParam("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 deleted file mode 100644 index 28553667b33b..000000000000 --- a/solr/api/src/java/org/apache/solr/client/api/model/ActiveTaskDetails.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.apache.solr.client.api.model; - -public class ActiveTaskDetails { - -} 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 index 826039cd8060..57e0af3b972a 100644 --- 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 @@ -2,8 +2,9 @@ import com.fasterxml.jackson.annotation.JsonProperty; import java.util.List; +import java.util.Map; public class ListActiveTaskResponse extends SolrJerseyResponse { @JsonProperty - public List taskList; + public Map taskList; } 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..8b6b1ffaf1de --- /dev/null +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/ListActiveTasks.java @@ -0,0 +1,40 @@ +package org.apache.solr.handler.admin.api; + +import jakarta.inject.Inject; +import org.apache.solr.api.JerseyResource; +import org.apache.solr.client.api.endpoint.ListActiveTasksApi; +import org.apache.solr.client.api.model.ListActiveTaskResponse; +import org.apache.solr.common.SolrException; +import org.apache.solr.core.CoreContainer; +import org.apache.solr.jersey.PermissionName; + +import java.util.Map; + +import static org.apache.solr.common.SolrException.ErrorCode.SERVER_ERROR; +import static org.apache.solr.security.PermissionNameProvider.Name.READ_PERM; + +public class ListActiveTasks extends JerseyResource implements ListActiveTasksApi { + + private final CoreContainer coreContainer; + + @Inject + public ListActiveTasks(CoreContainer coreContainer) { + this.coreContainer = coreContainer; + } + + @Override + @PermissionName(READ_PERM) + public ListActiveTaskResponse listActiveTasks(String taskUUID) throws Exception { + if (coreContainer == null || coreContainer.isShutDown()) { + throw new SolrException( + SERVER_ERROR, "CoreContainer is either not initialized or shutting down"); + } + + final ListActiveTaskResponse response = instantiateJerseyResponse(ListActiveTaskResponse.class); + + response.taskList = Map.of("xyz","jalaz"); + + return response; + + } +} 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..1785ba075fcd 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 @@ -21,14 +21,18 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Map; +import org.apache.solr.api.JerseyResource; import org.apache.solr.common.SolrException; import org.apache.solr.common.params.CommonParams; import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.core.CoreContainer; import org.apache.solr.core.SolrCore; import org.apache.solr.handler.RequestHandlerBase; +import org.apache.solr.handler.admin.api.ListActiveTasks; +import org.apache.solr.handler.admin.api.NodeHealth; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.response.SolrQueryResponse; import org.apache.solr.security.PermissionNameProvider; @@ -132,4 +136,9 @@ public static ResponseBuilder buildResponseBuilder( return rb; } + + @Override + public Collection> getJerseyResources() { + return List.of(ListActiveTasks.class); + } } From 7b157910c42aa8ec30db4b69df85772dfefeea6c Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 16 May 2026 16:27:35 +0530 Subject: [PATCH 03/70] working api --- .../solr/handler/admin/api/ListActiveTasks.java | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) 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 index 8b6b1ffaf1de..7c6faa48b941 100644 --- 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 @@ -4,35 +4,26 @@ import org.apache.solr.api.JerseyResource; import org.apache.solr.client.api.endpoint.ListActiveTasksApi; import org.apache.solr.client.api.model.ListActiveTaskResponse; -import org.apache.solr.common.SolrException; -import org.apache.solr.core.CoreContainer; import org.apache.solr.jersey.PermissionName; import java.util.Map; -import static org.apache.solr.common.SolrException.ErrorCode.SERVER_ERROR; import static org.apache.solr.security.PermissionNameProvider.Name.READ_PERM; public class ListActiveTasks extends JerseyResource implements ListActiveTasksApi { - private final CoreContainer coreContainer; - @Inject - public ListActiveTasks(CoreContainer coreContainer) { - this.coreContainer = coreContainer; + public ListActiveTasks() { + } @Override @PermissionName(READ_PERM) public ListActiveTaskResponse listActiveTasks(String taskUUID) throws Exception { - if (coreContainer == null || coreContainer.isShutDown()) { - throw new SolrException( - SERVER_ERROR, "CoreContainer is either not initialized or shutting down"); - } final ListActiveTaskResponse response = instantiateJerseyResponse(ListActiveTaskResponse.class); - response.taskList = Map.of("xyz","jalaz"); + response.taskList = Map.of("xyz","jalaz", "mno", "pqr"); return response; From 02c14b969c2c86bc9f141f0e0182811187e9794b Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 16 May 2026 18:59:25 +0530 Subject: [PATCH 04/70] working setup --- .../handler/admin/CollectionsHandler.java | 15 ++++++++++- .../handler/admin/api/ListActiveTasks.java | 27 ++++++++++++++++--- .../solr/common/params/CollectionParams.java | 1 + 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java index be9f394d26c5..41592f699533 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java @@ -97,6 +97,7 @@ import static org.apache.solr.common.params.CommonAdminParams.SPLIT_METHOD; import static org.apache.solr.common.params.CommonAdminParams.WAIT_FOR_FINAL_STATE; import static org.apache.solr.common.params.CommonParams.NAME; +import static org.apache.solr.common.params.CommonParams.TASK_CHECK_UUID; import static org.apache.solr.common.params.CommonParams.TIMING; import static org.apache.solr.common.params.CommonParams.VALUE_LONG; import static org.apache.solr.common.params.CoreAdminParams.BACKUP_LOCATION; @@ -124,6 +125,7 @@ import org.apache.solr.client.api.model.CreateCollectionSnapshotRequestBody; import org.apache.solr.client.api.model.CreateCollectionSnapshotResponse; import org.apache.solr.client.api.model.InstallShardDataRequestBody; +import org.apache.solr.client.api.model.ListActiveTaskResponse; import org.apache.solr.client.api.model.ListCollectionSnapshotsResponse; import org.apache.solr.client.api.model.ReplaceNodeRequestBody; import org.apache.solr.client.api.model.SetClusterPropertyRequestBody; @@ -194,6 +196,7 @@ import org.apache.solr.handler.admin.api.DeleteShard; import org.apache.solr.handler.admin.api.ForceLeader; import org.apache.solr.handler.admin.api.InstallShardData; +import org.apache.solr.handler.admin.api.ListActiveTasks; import org.apache.solr.handler.admin.api.ListAliases; import org.apache.solr.handler.admin.api.ListCollectionBackups; import org.apache.solr.handler.admin.api.ListCollectionSnapshots; @@ -958,6 +961,15 @@ public Map execute( V2ApiUtils.squashIntoSolrResponseWithoutHeader(rsp, listCollectionsResponse); return null; }), + /** Handle list of active tasks request. Do list collection request to zk host */ + LIST_TASK_OP( + LIST, + (req, rsp, h) -> { + final ListActiveTasks listActiveTasks = new ListActiveTasks(req); + final ListActiveTaskResponse listActiveTaskResponse = listActiveTasks.listActiveTasks(req.getParams().get(TASK_CHECK_UUID)); + V2ApiUtils.squashIntoSolrResponseWithoutHeader(rsp, listActiveTaskResponse); + return null; + }), /** * Handle cluster status request. Can return status per specific collection/shard or per all * collections. @@ -1377,7 +1389,8 @@ public Collection> getJerseyResources() { ListCollectionSnapshots.class, CreateCollectionSnapshot.class, DeleteCollectionSnapshot.class, - ClusterProperty.class); + ClusterProperty.class, + ListActiveTasks.class); } @Override 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 index 7c6faa48b941..03d187bebf49 100644 --- 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 @@ -4,26 +4,45 @@ import org.apache.solr.api.JerseyResource; import org.apache.solr.client.api.endpoint.ListActiveTasksApi; import org.apache.solr.client.api.model.ListActiveTaskResponse; +import org.apache.solr.core.CoreContainer; import org.apache.solr.jersey.PermissionName; +import org.apache.solr.request.SolrQueryRequest; +import org.apache.solr.response.SolrQueryResponse; +import java.util.HashMap; +import java.util.Iterator; import java.util.Map; +import static org.apache.solr.security.PermissionNameProvider.Name.COLL_READ_PERM; import static org.apache.solr.security.PermissionNameProvider.Name.READ_PERM; public class ListActiveTasks extends JerseyResource implements ListActiveTasksApi { - @Inject - public ListActiveTasks() { + private final SolrQueryRequest solrQueryRequest; + @Inject + public ListActiveTasks( + SolrQueryRequest solrQueryRequest) { + this.solrQueryRequest = solrQueryRequest; } + + @Override - @PermissionName(READ_PERM) + @PermissionName(COLL_READ_PERM) public ListActiveTaskResponse listActiveTasks(String taskUUID) throws Exception { final ListActiveTaskResponse response = instantiateJerseyResponse(ListActiveTaskResponse.class); - response.taskList = Map.of("xyz","jalaz", "mno", "pqr"); + Iterator> iterator = solrQueryRequest.getCore().getCancellableQueryTracker().getActiveQueriesGenerated(); + + Map taskList = new HashMap<>(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + taskList.put(entry.getKey(), entry.getValue()); + } + + response.taskList = taskList; return response; diff --git a/solr/solrj/src/java/org/apache/solr/common/params/CollectionParams.java b/solr/solrj/src/java/org/apache/solr/common/params/CollectionParams.java index a066ff1e89b3..2b92f60df478 100644 --- a/solr/solrj/src/java/org/apache/solr/common/params/CollectionParams.java +++ b/solr/solrj/src/java/org/apache/solr/common/params/CollectionParams.java @@ -114,6 +114,7 @@ enum CollectionAction { // For testing. Could eventually be exposed publicly if needed DISTRIBUTEDAPIPROCESSING(false, LockLevel.NONE), LIST(false, LockLevel.NONE), + LIST_TASK(false, LockLevel.NONE), CLUSTERSTATUS(false, LockLevel.NONE), ADDREPLICAPROP(true, LockLevel.NONE), // atomic; no lock DELETEREPLICAPROP(true, LockLevel.NONE), // atomic; no lock From 177d2c646843c126e3121c2136e6c6dca094021b Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 16 May 2026 19:34:11 +0530 Subject: [PATCH 05/70] cleanup --- .../solr/handler/admin/CollectionsHandler.java | 12 +----------- .../apache/solr/common/params/CollectionParams.java | 1 - 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java index 41592f699533..9f7b21a36efa 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java @@ -961,15 +961,6 @@ public Map execute( V2ApiUtils.squashIntoSolrResponseWithoutHeader(rsp, listCollectionsResponse); return null; }), - /** Handle list of active tasks request. Do list collection request to zk host */ - LIST_TASK_OP( - LIST, - (req, rsp, h) -> { - final ListActiveTasks listActiveTasks = new ListActiveTasks(req); - final ListActiveTaskResponse listActiveTaskResponse = listActiveTasks.listActiveTasks(req.getParams().get(TASK_CHECK_UUID)); - V2ApiUtils.squashIntoSolrResponseWithoutHeader(rsp, listActiveTaskResponse); - return null; - }), /** * Handle cluster status request. Can return status per specific collection/shard or per all * collections. @@ -1389,8 +1380,7 @@ public Collection> getJerseyResources() { ListCollectionSnapshots.class, CreateCollectionSnapshot.class, DeleteCollectionSnapshot.class, - ClusterProperty.class, - ListActiveTasks.class); + ClusterProperty.class); } @Override diff --git a/solr/solrj/src/java/org/apache/solr/common/params/CollectionParams.java b/solr/solrj/src/java/org/apache/solr/common/params/CollectionParams.java index 2b92f60df478..a066ff1e89b3 100644 --- a/solr/solrj/src/java/org/apache/solr/common/params/CollectionParams.java +++ b/solr/solrj/src/java/org/apache/solr/common/params/CollectionParams.java @@ -114,7 +114,6 @@ enum CollectionAction { // For testing. Could eventually be exposed publicly if needed DISTRIBUTEDAPIPROCESSING(false, LockLevel.NONE), LIST(false, LockLevel.NONE), - LIST_TASK(false, LockLevel.NONE), CLUSTERSTATUS(false, LockLevel.NONE), ADDREPLICAPROP(true, LockLevel.NONE), // atomic; no lock DELETEREPLICAPROP(true, LockLevel.NONE), // atomic; no lock From 95ace8df723035eab7fcb0e86bfc79b3a78f1c52 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 16 May 2026 19:49:25 +0530 Subject: [PATCH 06/70] cleanup --- .../apache/solr/client/api/endpoint/ListActiveTasksApi.java | 4 +--- .../apache/solr/client/api/model/ListActiveTaskResponse.java | 1 - .../org/apache/solr/handler/admin/CollectionsHandler.java | 3 --- .../org/apache/solr/handler/admin/api/ListActiveTasks.java | 5 +---- .../apache/solr/handler/component/TaskManagementHandler.java | 1 - 5 files changed, 2 insertions(+), 12 deletions(-) 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 index b76775456002..9c31458af815 100644 --- 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 @@ -1,10 +1,8 @@ package org.apache.solr.client.api.endpoint; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; import jakarta.ws.rs.QueryParam; import org.apache.solr.client.api.model.ListActiveTaskResponse; import org.apache.solr.client.api.util.StoreApiParameters; @@ -16,7 +14,7 @@ public interface ListActiveTasksApi { @GET @StoreApiParameters @Operation( - summary = "Lists all the currently running tasks", + summary = "Lists all the currently running tasks or status of any taskUUID being passed as queryParam", tags = {"tasks"}) ListActiveTaskResponse listActiveTasks( @QueryParam("taskUUID") String taskUUID) throws Exception; 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 index 57e0af3b972a..9885e0f7204f 100644 --- 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 @@ -1,7 +1,6 @@ package org.apache.solr.client.api.model; import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; import java.util.Map; public class ListActiveTaskResponse extends SolrJerseyResponse { diff --git a/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java index 9f7b21a36efa..be9f394d26c5 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java @@ -97,7 +97,6 @@ import static org.apache.solr.common.params.CommonAdminParams.SPLIT_METHOD; import static org.apache.solr.common.params.CommonAdminParams.WAIT_FOR_FINAL_STATE; import static org.apache.solr.common.params.CommonParams.NAME; -import static org.apache.solr.common.params.CommonParams.TASK_CHECK_UUID; import static org.apache.solr.common.params.CommonParams.TIMING; import static org.apache.solr.common.params.CommonParams.VALUE_LONG; import static org.apache.solr.common.params.CoreAdminParams.BACKUP_LOCATION; @@ -125,7 +124,6 @@ import org.apache.solr.client.api.model.CreateCollectionSnapshotRequestBody; import org.apache.solr.client.api.model.CreateCollectionSnapshotResponse; import org.apache.solr.client.api.model.InstallShardDataRequestBody; -import org.apache.solr.client.api.model.ListActiveTaskResponse; import org.apache.solr.client.api.model.ListCollectionSnapshotsResponse; import org.apache.solr.client.api.model.ReplaceNodeRequestBody; import org.apache.solr.client.api.model.SetClusterPropertyRequestBody; @@ -196,7 +194,6 @@ import org.apache.solr.handler.admin.api.DeleteShard; import org.apache.solr.handler.admin.api.ForceLeader; import org.apache.solr.handler.admin.api.InstallShardData; -import org.apache.solr.handler.admin.api.ListActiveTasks; import org.apache.solr.handler.admin.api.ListAliases; import org.apache.solr.handler.admin.api.ListCollectionBackups; import org.apache.solr.handler.admin.api.ListCollectionSnapshots; 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 index 03d187bebf49..bcd655df74f5 100644 --- 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 @@ -4,16 +4,13 @@ import org.apache.solr.api.JerseyResource; import org.apache.solr.client.api.endpoint.ListActiveTasksApi; import org.apache.solr.client.api.model.ListActiveTaskResponse; -import org.apache.solr.core.CoreContainer; import org.apache.solr.jersey.PermissionName; import org.apache.solr.request.SolrQueryRequest; -import org.apache.solr.response.SolrQueryResponse; import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import static org.apache.solr.security.PermissionNameProvider.Name.COLL_READ_PERM; import static org.apache.solr.security.PermissionNameProvider.Name.READ_PERM; public class ListActiveTasks extends JerseyResource implements ListActiveTasksApi { @@ -29,7 +26,7 @@ public ListActiveTasks( @Override - @PermissionName(COLL_READ_PERM) + @PermissionName(READ_PERM) public ListActiveTaskResponse listActiveTasks(String taskUUID) throws Exception { final ListActiveTaskResponse response = instantiateJerseyResponse(ListActiveTaskResponse.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 1785ba075fcd..817269b48c95 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 @@ -32,7 +32,6 @@ import org.apache.solr.core.SolrCore; import org.apache.solr.handler.RequestHandlerBase; import org.apache.solr.handler.admin.api.ListActiveTasks; -import org.apache.solr.handler.admin.api.NodeHealth; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.response.SolrQueryResponse; import org.apache.solr.security.PermissionNameProvider; From 7dc167a7e082dcf9182c837ee7234fc446b6bd6e Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 16 May 2026 20:01:10 +0530 Subject: [PATCH 07/70] logging --- .../solr/handler/admin/api/ListActiveTasks.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) 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 index bcd655df74f5..3c49a6fe1e09 100644 --- 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 @@ -4,9 +4,13 @@ import org.apache.solr.api.JerseyResource; import org.apache.solr.client.api.endpoint.ListActiveTasksApi; import org.apache.solr.client.api.model.ListActiveTaskResponse; +import org.apache.solr.core.CoreContainer; import org.apache.solr.jersey.PermissionName; import org.apache.solr.request.SolrQueryRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.lang.invoke.MethodHandles; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -15,6 +19,8 @@ public class ListActiveTasks extends JerseyResource implements ListActiveTasksApi { + private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + private final SolrQueryRequest solrQueryRequest; @Inject @@ -30,6 +36,13 @@ public ListActiveTasks( public ListActiveTaskResponse listActiveTasks(String taskUUID) throws Exception { final ListActiveTaskResponse response = instantiateJerseyResponse(ListActiveTaskResponse.class); + CoreContainer coreContainer = solrQueryRequest.getCoreContainer(); + + if (coreContainer.isZooKeeperAware()) { + log.debug("solr cloud"); + } else { + log.debug("stand alone"); + } Iterator> iterator = solrQueryRequest.getCore().getCancellableQueryTracker().getActiveQueriesGenerated(); From 1a32bb16439387e9f7c3ffe8cbbbc951ffee5418 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 16 May 2026 21:32:23 +0530 Subject: [PATCH 08/70] minor --- .../handler/admin/api/ListActiveTasks.java | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) 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 index 3c49a6fe1e09..6b7e22db7b15 100644 --- 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 @@ -39,11 +39,24 @@ public ListActiveTaskResponse listActiveTasks(String taskUUID) throws Exception CoreContainer coreContainer = solrQueryRequest.getCoreContainer(); if (coreContainer.isZooKeeperAware()) { - log.debug("solr cloud"); + if (log.isDebugEnabled()) { + log.debug("solr cloud"); + } + handleSolrCloudMode(response, taskUUID); } else { - log.debug("stand alone"); + if (log.isDebugEnabled()) { + log.debug("standalone solr"); + } + handleStandAloneMode(response, taskUUID); } + log.debug("something random"); + + return response; + + } + + private void handleStandAloneMode(ListActiveTaskResponse response, String taskUUID) { Iterator> iterator = solrQueryRequest.getCore().getCancellableQueryTracker().getActiveQueriesGenerated(); Map taskList = new HashMap<>(); @@ -53,8 +66,17 @@ public ListActiveTaskResponse listActiveTasks(String taskUUID) throws Exception } response.taskList = taskList; + } - return response; + private void handleSolrCloudMode(ListActiveTaskResponse response, String taskUUID) { + Iterator> iterator = solrQueryRequest.getCore().getCancellableQueryTracker().getActiveQueriesGenerated(); + Map taskList = new HashMap<>(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + taskList.put(entry.getKey(), entry.getValue()); + } + + response.taskList = taskList; } } From d746e210c8d3784b435c91e0a844765366d5cea8 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Wed, 20 May 2026 02:51:50 +0530 Subject: [PATCH 09/70] response model for 2nd API --- .../api/endpoint/ListActiveTasksApi.java | 20 +++++++++++----- .../client/api/model/TaskStatusResponse.java | 8 +++++++ .../handler/admin/api/ListActiveTasks.java | 23 ++++++++++++------- 3 files changed, 37 insertions(+), 14 deletions(-) create mode 100644 solr/api/src/java/org/apache/solr/client/api/model/TaskStatusResponse.java 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 index 9c31458af815..3b6ed8bc854f 100644 --- 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 @@ -3,19 +3,27 @@ import io.swagger.v3.oas.annotations.Operation; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; -import jakarta.ws.rs.QueryParam; +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; import static org.apache.solr.client.api.util.Constants.INDEX_PATH_PREFIX; @Path(INDEX_PATH_PREFIX + "/tasks/listjalaz") public interface ListActiveTasksApi { + + // Handles: .../tasks/listjalaz (Lists all) + @GET + @StoreApiParameters + @Operation(summary = "Lists all the currently running tasks", tags = {"tasks"}) + ListActiveTaskResponse listAllActiveTasks() throws Exception; + + // Handles: .../tasks/listjalaz/xyz (Lists specific) @GET + @Path("/{taskUUID}") @StoreApiParameters - @Operation( - summary = "Lists all the currently running tasks or status of any taskUUID being passed as queryParam", - tags = {"tasks"}) - ListActiveTaskResponse listActiveTasks( - @QueryParam("taskUUID") String taskUUID) throws Exception; + @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/TaskStatusResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/TaskStatusResponse.java new file mode 100644 index 000000000000..da691675468f --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/TaskStatusResponse.java @@ -0,0 +1,8 @@ +package org.apache.solr.client.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class TaskStatusResponse extends SolrJerseyResponse { + @JsonProperty + public boolean 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 index 6b7e22db7b15..b902eb005b4c 100644 --- 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 @@ -4,6 +4,7 @@ import org.apache.solr.api.JerseyResource; import org.apache.solr.client.api.endpoint.ListActiveTasksApi; import org.apache.solr.client.api.model.ListActiveTaskResponse; +import org.apache.solr.client.api.model.TaskStatusResponse; import org.apache.solr.core.CoreContainer; import org.apache.solr.jersey.PermissionName; import org.apache.solr.request.SolrQueryRequest; @@ -29,12 +30,9 @@ public ListActiveTasks( this.solrQueryRequest = solrQueryRequest; } - - @Override @PermissionName(READ_PERM) - public ListActiveTaskResponse listActiveTasks(String taskUUID) throws Exception { - + public ListActiveTaskResponse listAllActiveTasks() throws Exception { final ListActiveTaskResponse response = instantiateJerseyResponse(ListActiveTaskResponse.class); CoreContainer coreContainer = solrQueryRequest.getCoreContainer(); @@ -42,21 +40,28 @@ public ListActiveTaskResponse listActiveTasks(String taskUUID) throws Exception if (log.isDebugEnabled()) { log.debug("solr cloud"); } - handleSolrCloudMode(response, taskUUID); + handleSolrCloudMode(response); } else { if (log.isDebugEnabled()) { log.debug("standalone solr"); } - handleStandAloneMode(response, taskUUID); + handleStandAloneMode(response); } log.debug("something random"); return response; + } + @Override + @PermissionName(READ_PERM) + public TaskStatusResponse getTaskStatus(String taskUUID) throws Exception { + return null; } - private void handleStandAloneMode(ListActiveTaskResponse response, String taskUUID) { + + + private void handleStandAloneMode(ListActiveTaskResponse response) { Iterator> iterator = solrQueryRequest.getCore().getCancellableQueryTracker().getActiveQueriesGenerated(); Map taskList = new HashMap<>(); @@ -68,7 +73,7 @@ private void handleStandAloneMode(ListActiveTaskResponse response, String taskUU response.taskList = taskList; } - private void handleSolrCloudMode(ListActiveTaskResponse response, String taskUUID) { + private void handleSolrCloudMode(ListActiveTaskResponse response) { Iterator> iterator = solrQueryRequest.getCore().getCancellableQueryTracker().getActiveQueriesGenerated(); Map taskList = new HashMap<>(); @@ -79,4 +84,6 @@ private void handleSolrCloudMode(ListActiveTaskResponse response, String taskUUI response.taskList = taskList; } + + } From df5c42883edda7540cc0129c52b9f5551a63c633 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Wed, 20 May 2026 04:05:24 +0530 Subject: [PATCH 10/70] verifies for solr cloud --- .../handler/admin/api/ListActiveTasks.java | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) 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 index b902eb005b4c..978aaa8d6f4f 100644 --- 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 @@ -40,28 +40,41 @@ public ListActiveTaskResponse listAllActiveTasks() throws Exception { if (log.isDebugEnabled()) { log.debug("solr cloud"); } - handleSolrCloudMode(response); + response.taskList = handleSolrCloudMode(); } else { if (log.isDebugEnabled()) { log.debug("standalone solr"); } - handleStandAloneMode(response); + response.taskList = handleStandAloneMode(); } - log.debug("something random"); - return response; } @Override @PermissionName(READ_PERM) public TaskStatusResponse getTaskStatus(String taskUUID) throws Exception { - return null; + final TaskStatusResponse response = instantiateJerseyResponse(TaskStatusResponse.class); + CoreContainer coreContainer = solrQueryRequest.getCoreContainer(); + + if (coreContainer.isZooKeeperAware()) { + if (log.isDebugEnabled()) { + log.debug("solr cloud"); + } + response.taskStatus = solrQueryRequest.getCore().getCancellableQueryTracker().isQueryIdActive(taskUUID); + } else { + if (log.isDebugEnabled()) { + log.debug("standalone solr"); + } + response.taskStatus = solrQueryRequest.getCore().getCancellableQueryTracker().isQueryIdActive(taskUUID); + } + + return response; } - private void handleStandAloneMode(ListActiveTaskResponse response) { + private Map handleStandAloneMode() { Iterator> iterator = solrQueryRequest.getCore().getCancellableQueryTracker().getActiveQueriesGenerated(); Map taskList = new HashMap<>(); @@ -70,10 +83,10 @@ private void handleStandAloneMode(ListActiveTaskResponse response) { taskList.put(entry.getKey(), entry.getValue()); } - response.taskList = taskList; + return taskList; } - private void handleSolrCloudMode(ListActiveTaskResponse response) { + private Map handleSolrCloudMode() { Iterator> iterator = solrQueryRequest.getCore().getCancellableQueryTracker().getActiveQueriesGenerated(); Map taskList = new HashMap<>(); @@ -82,7 +95,7 @@ private void handleSolrCloudMode(ListActiveTaskResponse response) { taskList.put(entry.getKey(), entry.getValue()); } - response.taskList = taskList; + return taskList; } From 354d0f5e733dde8a7a3838d06073f5a8a053db94 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Wed, 20 May 2026 23:51:26 +0530 Subject: [PATCH 11/70] changes related to pojo & duplicate code removal --- .../client/api/model/ActiveTaskDetails.java | 17 +++++ .../api/model/ListActiveTaskResponse.java | 4 +- .../handler/admin/api/ListActiveTasks.java | 63 ++++--------------- 3 files changed, 30 insertions(+), 54 deletions(-) create mode 100644 solr/api/src/java/org/apache/solr/client/api/model/ActiveTaskDetails.java 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..c7c58f073c43 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/ActiveTaskDetails.java @@ -0,0 +1,17 @@ +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 index 9885e0f7204f..826039cd8060 100644 --- 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 @@ -1,9 +1,9 @@ package org.apache.solr.client.api.model; import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.Map; +import java.util.List; public class ListActiveTaskResponse extends SolrJerseyResponse { @JsonProperty - public Map taskList; + public List taskList; } 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 index 978aaa8d6f4f..da7aa2093346 100644 --- 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 @@ -3,25 +3,21 @@ import jakarta.inject.Inject; 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.core.CoreContainer; import org.apache.solr.jersey.PermissionName; import org.apache.solr.request.SolrQueryRequest; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import java.lang.invoke.MethodHandles; -import java.util.HashMap; +import java.util.ArrayList; import java.util.Iterator; +import java.util.List; import java.util.Map; import static org.apache.solr.security.PermissionNameProvider.Name.READ_PERM; public class ListActiveTasks extends JerseyResource implements ListActiveTasksApi { - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - private final SolrQueryRequest solrQueryRequest; @Inject @@ -34,19 +30,8 @@ public ListActiveTasks( @PermissionName(READ_PERM) public ListActiveTaskResponse listAllActiveTasks() throws Exception { final ListActiveTaskResponse response = instantiateJerseyResponse(ListActiveTaskResponse.class); - CoreContainer coreContainer = solrQueryRequest.getCoreContainer(); - - if (coreContainer.isZooKeeperAware()) { - if (log.isDebugEnabled()) { - log.debug("solr cloud"); - } - response.taskList = handleSolrCloudMode(); - } else { - if (log.isDebugEnabled()) { - log.debug("standalone solr"); - } - response.taskList = handleStandAloneMode(); - } + + response.taskList = extractActiveTaskLists(); return response; } @@ -55,48 +40,22 @@ public ListActiveTaskResponse listAllActiveTasks() throws Exception { @PermissionName(READ_PERM) public TaskStatusResponse getTaskStatus(String taskUUID) throws Exception { final TaskStatusResponse response = instantiateJerseyResponse(TaskStatusResponse.class); - CoreContainer coreContainer = solrQueryRequest.getCoreContainer(); - - if (coreContainer.isZooKeeperAware()) { - if (log.isDebugEnabled()) { - log.debug("solr cloud"); - } - response.taskStatus = solrQueryRequest.getCore().getCancellableQueryTracker().isQueryIdActive(taskUUID); - } else { - if (log.isDebugEnabled()) { - log.debug("standalone solr"); - } - response.taskStatus = solrQueryRequest.getCore().getCancellableQueryTracker().isQueryIdActive(taskUUID); - } - - return response; - } - + response.taskStatus = solrQueryRequest.getCore().getCancellableQueryTracker().isQueryIdActive(taskUUID); - private Map handleStandAloneMode() { - Iterator> iterator = solrQueryRequest.getCore().getCancellableQueryTracker().getActiveQueriesGenerated(); - - Map taskList = new HashMap<>(); - while (iterator.hasNext()) { - Map.Entry entry = iterator.next(); - taskList.put(entry.getKey(), entry.getValue()); - } - - return taskList; + return response; } - private Map handleSolrCloudMode() { + private List extractActiveTaskLists() { Iterator> iterator = solrQueryRequest.getCore().getCancellableQueryTracker().getActiveQueriesGenerated(); - Map taskList = new HashMap<>(); + List activeTaskDetails = new ArrayList<>(); while (iterator.hasNext()) { Map.Entry entry = iterator.next(); - taskList.put(entry.getKey(), entry.getValue()); + activeTaskDetails.add(new ActiveTaskDetails(entry.getKey(), entry.getValue())); } - return taskList; + return activeTaskDetails; } - } From 1cad09dedffecf3a6fa8403ca5aeaa35532a365d Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Thu, 21 May 2026 00:50:31 +0530 Subject: [PATCH 12/70] removed older interfaces --- .../component/ActiveTasksListComponent.java | 128 ------------------ .../component/ActiveTasksListHandler.java | 44 +++--- .../component/TaskManagementHandler.java | 7 - 3 files changed, 18 insertions(+), 161 deletions(-) delete mode 100644 solr/core/src/java/org/apache/solr/handler/component/ActiveTasksListComponent.java 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..82c9f1a26349 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,44 +19,38 @@ 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.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); - } - - rb.setTaskStatusCheckUUID(taskStatusCheckUUID); + V2ApiUtils.squashIntoSolrResponseWithoutHeader(rsp, new ListActiveTasks(req).getTaskStatus(taskStatusCheckUUID)); + } else { + V2ApiUtils.squashIntoSolrResponseWithoutHeader(rsp, new ListActiveTasks(req).listAllActiveTasks()); } - processRequest(req, rb, extraParams); } @Override @@ -90,14 +84,12 @@ 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 817269b48c95..630c15de74d1 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 @@ -118,9 +118,6 @@ public static List buildComponentsList() { QueryCancellationComponent component = new QueryCancellationComponent(); components.add(component); - ActiveTasksListComponent activeTasksListComponent = new ActiveTasksListComponent(); - components.add(activeTasksListComponent); - return components; } @@ -136,8 +133,4 @@ public static ResponseBuilder buildResponseBuilder( return rb; } - @Override - public Collection> getJerseyResources() { - return List.of(ListActiveTasks.class); - } } From 579925d3fe6054fa59207d2cb6a73d91a0222677 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Thu, 21 May 2026 00:56:22 +0530 Subject: [PATCH 13/70] removing debug --- .../apache/solr/client/api/endpoint/ListActiveTasksApi.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 index 3b6ed8bc854f..8a373d9bef32 100644 --- 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 @@ -10,16 +10,16 @@ import static org.apache.solr.client.api.util.Constants.INDEX_PATH_PREFIX; -@Path(INDEX_PATH_PREFIX + "/tasks/listjalaz") +@Path(INDEX_PATH_PREFIX + "/tasks/list") public interface ListActiveTasksApi { - // Handles: .../tasks/listjalaz (Lists all) + // Handles: .../tasks/list (Lists all) @GET @StoreApiParameters @Operation(summary = "Lists all the currently running tasks", tags = {"tasks"}) ListActiveTaskResponse listAllActiveTasks() throws Exception; - // Handles: .../tasks/listjalaz/xyz (Lists specific) + // Handles: .../tasks/list/xyz (Lists specific) @GET @Path("/{taskUUID}") @StoreApiParameters From eb1cd97d75c099ad20bf983f13a6dbefb849d003 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Thu, 21 May 2026 03:26:16 +0530 Subject: [PATCH 14/70] done --- .../component/ActiveTasksListHandler.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) 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 82c9f1a26349..0763cda74147 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,9 +19,12 @@ 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.Api; import org.apache.solr.api.JerseyResource; +import org.apache.solr.client.api.model.ActiveTaskDetails; import org.apache.solr.handler.admin.api.ListActiveTasks; import org.apache.solr.handler.api.V2ApiUtils; import org.apache.solr.request.SolrQueryRequest; @@ -48,14 +51,22 @@ public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throw if (taskStatusCheckUUID != null) { V2ApiUtils.squashIntoSolrResponseWithoutHeader(rsp, new ListActiveTasks(req).getTaskStatus(taskStatusCheckUUID)); } else { - V2ApiUtils.squashIntoSolrResponseWithoutHeader(rsp, new ListActiveTasks(req).listAllActiveTasks()); + Map mapTasks = new HashMap<>(); + List taskList = new ListActiveTasks(req).listAllActiveTasks().taskList; + if (taskList != null) { + for (ActiveTaskDetails task : taskList) { + mapTasks.put(task.taskUUID, task.taskQuery); + } + } + rsp.add("taskList", mapTasks); } - } + // ////////////////////// SolrInfoMBeans methods ////////////////////// + @Override public String getDescription() { - return "activetaskslist"; + return "Active Tasks List"; } @Override @@ -73,7 +84,6 @@ public SolrRequestHandler getSubHandler(String path) { if (path.startsWith("/tasks/list")) { return this; } - return null; } From 4e10720ae432aa6321cc0446fdbc9caf8d7a2cd7 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Thu, 21 May 2026 03:29:05 +0530 Subject: [PATCH 15/70] self review --- .../apache/solr/client/api/endpoint/ListActiveTasksApi.java | 2 +- .../apache/solr/handler/component/ActiveTasksListHandler.java | 1 - .../apache/solr/handler/component/TaskManagementHandler.java | 4 ---- 3 files changed, 1 insertion(+), 6 deletions(-) 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 index 8a373d9bef32..e5de534a7f5c 100644 --- 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 @@ -19,7 +19,7 @@ public interface ListActiveTasksApi { @Operation(summary = "Lists all the currently running tasks", tags = {"tasks"}) ListActiveTaskResponse listAllActiveTasks() throws Exception; - // Handles: .../tasks/list/xyz (Lists specific) + // Handles: .../tasks/list/slow-task-id (Lists specific) @GET @Path("/{taskUUID}") @StoreApiParameters 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 0763cda74147..6991bc942865 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 @@ -36,7 +36,6 @@ /** * 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. */ 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 630c15de74d1..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 @@ -21,17 +21,14 @@ import java.io.IOException; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.Map; -import org.apache.solr.api.JerseyResource; import org.apache.solr.common.SolrException; import org.apache.solr.common.params.CommonParams; import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.core.CoreContainer; import org.apache.solr.core.SolrCore; import org.apache.solr.handler.RequestHandlerBase; -import org.apache.solr.handler.admin.api.ListActiveTasks; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.response.SolrQueryResponse; import org.apache.solr.security.PermissionNameProvider; @@ -132,5 +129,4 @@ public static ResponseBuilder buildResponseBuilder( return rb; } - } From eb9b51b265cf023d00ae8d2f8df50487ba4f1bb7 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Thu, 21 May 2026 03:40:00 +0530 Subject: [PATCH 16/70] added cl --- changelog/unreleased/SOLR-18248-list-tasks.yml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 changelog/unreleased/SOLR-18248-list-tasks.yml 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 From adc7006aa78c46592eea9f1cf385182384103b61 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Thu, 21 May 2026 03:45:00 +0530 Subject: [PATCH 17/70] tidying done --- .../api/endpoint/ListActiveTasksApi.java | 15 +++++++----- .../client/api/model/ActiveTaskDetails.java | 1 - .../api/model/ListActiveTaskResponse.java | 3 +-- .../client/api/model/TaskStatusResponse.java | 3 +-- .../handler/admin/api/ListActiveTasks.java | 23 +++++++++---------- .../component/ActiveTasksListHandler.java | 11 ++++----- 6 files changed, 27 insertions(+), 29 deletions(-) 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 index e5de534a7f5c..d857a7541637 100644 --- 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 @@ -1,5 +1,7 @@ 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; @@ -8,22 +10,23 @@ import org.apache.solr.client.api.model.TaskStatusResponse; import org.apache.solr.client.api.util.StoreApiParameters; -import static org.apache.solr.client.api.util.Constants.INDEX_PATH_PREFIX; - @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"}) + @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; + @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 index c7c58f073c43..750638acdb46 100644 --- 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 @@ -13,5 +13,4 @@ public ActiveTaskDetails(String taskUUID, String 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 index 826039cd8060..f04771650c19 100644 --- 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 @@ -4,6 +4,5 @@ import java.util.List; public class ListActiveTaskResponse extends SolrJerseyResponse { - @JsonProperty - public List taskList; + @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 index da691675468f..843df81bceed 100644 --- 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 @@ -3,6 +3,5 @@ import com.fasterxml.jackson.annotation.JsonProperty; public class TaskStatusResponse extends SolrJerseyResponse { - @JsonProperty - public boolean taskStatus; + @JsonProperty public boolean 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 index da7aa2093346..672fd7e0115a 100644 --- 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 @@ -1,6 +1,12 @@ 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; @@ -9,20 +15,12 @@ import org.apache.solr.jersey.PermissionName; import org.apache.solr.request.SolrQueryRequest; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import static org.apache.solr.security.PermissionNameProvider.Name.READ_PERM; - public class ListActiveTasks extends JerseyResource implements ListActiveTasksApi { private final SolrQueryRequest solrQueryRequest; @Inject - public ListActiveTasks( - SolrQueryRequest solrQueryRequest) { + public ListActiveTasks(SolrQueryRequest solrQueryRequest) { this.solrQueryRequest = solrQueryRequest; } @@ -41,13 +39,15 @@ public ListActiveTaskResponse listAllActiveTasks() throws Exception { public TaskStatusResponse getTaskStatus(String taskUUID) throws Exception { final TaskStatusResponse response = instantiateJerseyResponse(TaskStatusResponse.class); - response.taskStatus = solrQueryRequest.getCore().getCancellableQueryTracker().isQueryIdActive(taskUUID); + response.taskStatus = + solrQueryRequest.getCore().getCancellableQueryTracker().isQueryIdActive(taskUUID); return response; } private List extractActiveTaskLists() { - Iterator> iterator = solrQueryRequest.getCore().getCancellableQueryTracker().getActiveQueriesGenerated(); + Iterator> iterator = + solrQueryRequest.getCore().getCancellableQueryTracker().getActiveQueriesGenerated(); List activeTaskDetails = new ArrayList<>(); while (iterator.hasNext()) { @@ -57,5 +57,4 @@ private List extractActiveTaskLists() { return activeTaskDetails; } - } 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 6991bc942865..30d6dd68b52b 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 @@ -33,11 +33,10 @@ import org.apache.solr.security.AuthorizationContext; import org.apache.solr.security.PermissionNameProvider; - /** - * 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. + * 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 @@ -48,7 +47,8 @@ public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throw String taskStatusCheckUUID = req.getParams().get(TASK_CHECK_UUID, null); if (taskStatusCheckUUID != null) { - V2ApiUtils.squashIntoSolrResponseWithoutHeader(rsp, new ListActiveTasks(req).getTaskStatus(taskStatusCheckUUID)); + V2ApiUtils.squashIntoSolrResponseWithoutHeader( + rsp, new ListActiveTasks(req).getTaskStatus(taskStatusCheckUUID)); } else { Map mapTasks = new HashMap<>(); List taskList = new ListActiveTasks(req).listAllActiveTasks().taskList; @@ -100,5 +100,4 @@ public Collection getApis() { public Collection> getJerseyResources() { return List.of(ListActiveTasks.class); } - } From 996b45b2eb2d8be47884ad96c3c4ad87b37b9b61 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Thu, 21 May 2026 03:53:07 +0530 Subject: [PATCH 18/70] added apache license --- .../api/endpoint/ListActiveTasksApi.java | 17 +++++++ .../client/api/model/ActiveTaskDetails.java | 17 +++++++ .../api/model/ListActiveTaskResponse.java | 17 +++++++ .../client/api/model/TaskStatusResponse.java | 17 +++++++ .../handler/admin/api/ListActiveTasks.java | 17 +++++++ .../handler/admin/api/ListActiveTasksAPI.java | 48 ------------------- 6 files changed, 85 insertions(+), 48 deletions(-) delete mode 100644 solr/core/src/java/org/apache/solr/handler/admin/api/ListActiveTasksAPI.java 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 index d857a7541637..b42a8cb38f1c 100644 --- 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 @@ -1,3 +1,20 @@ +/* + * 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; 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 index 750638acdb46..874267024f58 100644 --- 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 @@ -1,3 +1,20 @@ +/* + * 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; 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 index f04771650c19..f74ec9096077 100644 --- 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 @@ -1,3 +1,20 @@ +/* + * 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; 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 index 843df81bceed..9a1c700873dd 100644 --- 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 @@ -1,3 +1,20 @@ +/* + * 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; 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 index 672fd7e0115a..6d71505e281b 100644 --- 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 @@ -1,3 +1,20 @@ +/* + * 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; 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); - } -} From f6cb8f719813a94f8b997b1c1d3b702a6f210a2a Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 23 May 2026 03:32:14 +0530 Subject: [PATCH 19/70] tests --- .../admin/api/ListActiveTasksTest.java | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 solr/core/src/test/org/apache/solr/handler/admin/api/ListActiveTasksTest.java 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..a4a473b7e8d5 --- /dev/null +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/ListActiveTasksTest.java @@ -0,0 +1,60 @@ +package org.apache.solr.handler.admin.api; + +import io.opentelemetry.api.trace.Span; +import org.apache.solr.SolrTestCaseJ4; +import org.apache.solr.client.api.model.ActiveTaskDetails; +import org.apache.solr.client.api.model.ListActiveTaskResponse; +import org.apache.solr.client.api.model.ListAliasesResponse; +import org.apache.solr.cloud.ZkController; +import org.apache.solr.common.cloud.Aliases; +import org.apache.solr.common.cloud.ZkStateReader; +import org.apache.solr.core.CoreContainer; +import org.apache.solr.request.SolrQueryRequest; +import org.apache.solr.response.SolrQueryResponse; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class ListActiveTasksTest extends SolrTestCaseJ4 { + + private SolrQueryRequest mockQueryRequest; + + private ListActiveTasks listActiveTasks; + + @BeforeClass + public static void ensureWorkingMockito() { + assumeWorkingMockito(); + } + + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + + mockQueryRequest = mock(SolrQueryRequest.class); + + listActiveTasks = new ListActiveTasks(mockQueryRequest); + } + + @Test + public void testGetActiveTasks() throws Exception { + + Map myMap = new HashMap<>(); + myMap.put("Key1", "Value1"); + myMap.put("Key2", "Value2"); + Iterator> mockIterator = myMap.entrySet().iterator(); + + when(mockQueryRequest.getCore().getCancellableQueryTracker().getActiveQueriesGenerated()).thenReturn(mockIterator); + + ListActiveTaskResponse response = listActiveTasks.listAllActiveTasks(); + + } + +} From 97e5afa64fa8b64cc3b58bc0a8948333a9bbf0cd Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 23 May 2026 16:02:27 +0530 Subject: [PATCH 20/70] added 1 test --- .../admin/api/ListActiveTasksTest.java | 61 +++++++++++++------ 1 file changed, 42 insertions(+), 19 deletions(-) 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 index a4a473b7e8d5..acaffbdddb4e 100644 --- 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 @@ -1,30 +1,26 @@ package org.apache.solr.handler.admin.api; -import io.opentelemetry.api.trace.Span; +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.ActiveTaskDetails; import org.apache.solr.client.api.model.ListActiveTaskResponse; -import org.apache.solr.client.api.model.ListAliasesResponse; -import org.apache.solr.cloud.ZkController; -import org.apache.solr.common.cloud.Aliases; -import org.apache.solr.common.cloud.ZkStateReader; -import org.apache.solr.core.CoreContainer; +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.apache.solr.response.SolrQueryResponse; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - public class ListActiveTasksTest extends SolrTestCaseJ4 { private SolrQueryRequest mockQueryRequest; + private SolrCore solrCore; + private CancellableQueryTracker cancellableQueryTracker; private ListActiveTasks listActiveTasks; @@ -39,6 +35,8 @@ public void setUp() throws Exception { super.setUp(); mockQueryRequest = mock(SolrQueryRequest.class); + solrCore = mock(SolrCore.class); + cancellableQueryTracker = mock(CancellableQueryTracker.class); listActiveTasks = new ListActiveTasks(mockQueryRequest); } @@ -46,15 +44,40 @@ public void setUp() throws Exception { @Test public void testGetActiveTasks() throws Exception { - Map myMap = new HashMap<>(); - myMap.put("Key1", "Value1"); - myMap.put("Key2", "Value2"); + 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().getCancellableQueryTracker().getActiveQueriesGenerated()).thenReturn(mockIterator); + 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); + assertNull(responseRunningTask.error); + + TaskStatusResponse responseStoppedTask = listActiveTasks.getTaskStatus("taskID_stopped"); + assertFalse(responseStoppedTask.taskStatus); + assertNull(responseStoppedTask.error); + } } From 3d72214eb82bee0d0bb23cbf02bedc9e4cd930b7 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 23 May 2026 21:07:24 +0530 Subject: [PATCH 21/70] added license --- .../handler/admin/api/ListActiveTasksTest.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) 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 index acaffbdddb4e..22a86ad00a14 100644 --- 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 @@ -1,3 +1,20 @@ +/* + * 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; From 68eec354cdbe3856f5dd5464dd55f9c317c63c1c Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sun, 24 May 2026 16:40:38 +0530 Subject: [PATCH 22/70] test corrections --- .../apache/solr/client/api/model/TaskStatusResponse.java | 2 +- .../apache/solr/handler/admin/api/ListActiveTasks.java | 9 +++++++-- .../solr/handler/component/ActiveTasksListHandler.java | 7 ++++--- .../solr/handler/admin/api/ListActiveTasksTest.java | 4 ++-- 4 files changed, 14 insertions(+), 8 deletions(-) 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 index 9a1c700873dd..6cae72670d7c 100644 --- 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 @@ -20,5 +20,5 @@ import com.fasterxml.jackson.annotation.JsonProperty; public class TaskStatusResponse extends SolrJerseyResponse { - @JsonProperty public boolean taskStatus; + @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 index 6d71505e281b..ab8a1459b840 100644 --- 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 @@ -56,8 +56,13 @@ public ListActiveTaskResponse listAllActiveTasks() throws Exception { public TaskStatusResponse getTaskStatus(String taskUUID) throws Exception { final TaskStatusResponse response = instantiateJerseyResponse(TaskStatusResponse.class); - response.taskStatus = - solrQueryRequest.getCore().getCancellableQueryTracker().isQueryIdActive(taskUUID); + + boolean isTaskActive = solrQueryRequest.getCore().getCancellableQueryTracker().isQueryIdActive(taskUUID); + if (isTaskActive) { + response.taskStatus = "id: "+ taskUUID + ", status: active"; + } else { + response.taskStatus = "id: "+ taskUUID + ", status: inactive"; + } return response; } 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 30d6dd68b52b..9fd25bcde501 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 @@ -25,6 +25,7 @@ import org.apache.solr.api.Api; 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; @@ -50,14 +51,14 @@ public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throw V2ApiUtils.squashIntoSolrResponseWithoutHeader( rsp, new ListActiveTasks(req).getTaskStatus(taskStatusCheckUUID)); } else { - Map mapTasks = new HashMap<>(); + NamedList tasks = new NamedList<>(); List taskList = new ListActiveTasks(req).listAllActiveTasks().taskList; if (taskList != null) { for (ActiveTaskDetails task : taskList) { - mapTasks.put(task.taskUUID, task.taskQuery); + tasks.add(task.taskUUID, task.taskQuery); } } - rsp.add("taskList", mapTasks); + rsp.add("taskList", tasks); } } 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 index 22a86ad00a14..7fb8114e0726 100644 --- 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 @@ -90,11 +90,11 @@ public void testGetTaskStatus() throws Exception { when(cancellableQueryTracker.isQueryIdActive("taskID_stopped")).thenReturn(false); TaskStatusResponse responseRunningTask = listActiveTasks.getTaskStatus("taskID_running"); - assertTrue(responseRunningTask.taskStatus); + assertTrue(responseRunningTask.taskStatus.contains("active")); assertNull(responseRunningTask.error); TaskStatusResponse responseStoppedTask = listActiveTasks.getTaskStatus("taskID_stopped"); - assertFalse(responseStoppedTask.taskStatus); + assertTrue(responseStoppedTask.taskStatus.contains("inactive")); assertNull(responseStoppedTask.error); } } From 87204e22104396b75555e5174ccad1ea7dbfc67e Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sun, 24 May 2026 16:45:32 +0530 Subject: [PATCH 23/70] minor tidy --- .../apache/solr/handler/admin/api/ListActiveTasks.java | 8 ++++---- .../solr/handler/component/ActiveTasksListHandler.java | 2 -- 2 files changed, 4 insertions(+), 6 deletions(-) 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 index ab8a1459b840..ea3fd00a4426 100644 --- 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 @@ -56,12 +56,12 @@ public ListActiveTaskResponse listAllActiveTasks() throws Exception { public TaskStatusResponse getTaskStatus(String taskUUID) throws Exception { final TaskStatusResponse response = instantiateJerseyResponse(TaskStatusResponse.class); - - boolean isTaskActive = solrQueryRequest.getCore().getCancellableQueryTracker().isQueryIdActive(taskUUID); + boolean isTaskActive = + solrQueryRequest.getCore().getCancellableQueryTracker().isQueryIdActive(taskUUID); if (isTaskActive) { - response.taskStatus = "id: "+ taskUUID + ", status: active"; + response.taskStatus = "id: " + taskUUID + ", status: active"; } else { - response.taskStatus = "id: "+ taskUUID + ", status: inactive"; + response.taskStatus = "id: " + taskUUID + ", status: inactive"; } return response; 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 9fd25bcde501..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,9 +19,7 @@ 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.Api; import org.apache.solr.api.JerseyResource; import org.apache.solr.client.api.model.ActiveTaskDetails; From 930312b848b6f0fb59647d9509c4c9285798c70a Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sun, 24 May 2026 17:38:29 +0530 Subject: [PATCH 24/70] test to check actual active/inactive --- .../solr/search/TestTaskManagement.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) 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( From 199cb2453cfb9a1b680b45ed35143767c54049ba Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Fri, 29 May 2026 00:48:37 +0530 Subject: [PATCH 25/70] comments addressal --- .../{ListActiveTasksApi.java => TasksApi.java} | 10 ++++------ .../solr/client/api/model/ActiveTaskDetails.java | 6 +++--- .../solr/handler/admin/api/ListActiveTasks.java | 12 ++++++------ .../handler/component/ActiveTasksListHandler.java | 2 +- .../solr/handler/admin/api/ListActiveTasksTest.java | 4 ++-- 5 files changed, 16 insertions(+), 18 deletions(-) rename solr/api/src/java/org/apache/solr/client/api/endpoint/{ListActiveTasksApi.java => TasksApi.java} (84%) 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/TasksApi.java similarity index 84% rename from solr/api/src/java/org/apache/solr/client/api/endpoint/ListActiveTasksApi.java rename to solr/api/src/java/org/apache/solr/client/api/endpoint/TasksApi.java index b42a8cb38f1c..1c9cb95e4193 100644 --- a/solr/api/src/java/org/apache/solr/client/api/endpoint/ListActiveTasksApi.java +++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/TasksApi.java @@ -27,10 +27,9 @@ 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 { +@Path(INDEX_PATH_PREFIX + "/tasks") +public interface TasksApi { - // Handles: .../tasks/list (Lists all) @GET @StoreApiParameters @Operation( @@ -38,12 +37,11 @@ public interface ListActiveTasksApi { tags = {"tasks"}) ListActiveTaskResponse listAllActiveTasks() throws Exception; - // Handles: .../tasks/list/slow-task-id (Lists specific) @GET - @Path("/{taskUUID}") + @Path("/{taskID}") @StoreApiParameters @Operation( summary = "Status of a specific taskUUID passed as pathParam", tags = {"tasks"}) - TaskStatusResponse getTaskStatus(@PathParam("taskUUID") String taskUUID) throws Exception; + TaskStatusResponse getTaskStatus(@PathParam("taskID") String taskID) 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 index 874267024f58..8781623c5c95 100644 --- 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 @@ -23,11 +23,11 @@ public class ActiveTaskDetails { public ActiveTaskDetails() {} - public ActiveTaskDetails(String taskUUID, String taskQuery) { - this.taskUUID = taskUUID; + public ActiveTaskDetails(String taskID, String taskQuery) { + this.taskID = taskID; this.taskQuery = taskQuery; } - @JsonProperty public String taskUUID; + @JsonProperty public String taskID; @JsonProperty public String taskQuery; } 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 index ea3fd00a4426..c2becbcbd43e 100644 --- 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 @@ -25,14 +25,14 @@ 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.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.jersey.PermissionName; import org.apache.solr.request.SolrQueryRequest; -public class ListActiveTasks extends JerseyResource implements ListActiveTasksApi { +public class ListActiveTasks extends JerseyResource implements TasksApi { private final SolrQueryRequest solrQueryRequest; @@ -53,15 +53,15 @@ public ListActiveTaskResponse listAllActiveTasks() throws Exception { @Override @PermissionName(READ_PERM) - public TaskStatusResponse getTaskStatus(String taskUUID) throws Exception { + public TaskStatusResponse getTaskStatus(String taskID) throws Exception { final TaskStatusResponse response = instantiateJerseyResponse(TaskStatusResponse.class); boolean isTaskActive = - solrQueryRequest.getCore().getCancellableQueryTracker().isQueryIdActive(taskUUID); + solrQueryRequest.getCore().getCancellableQueryTracker().isQueryIdActive(taskID); if (isTaskActive) { - response.taskStatus = "id: " + taskUUID + ", status: active"; + response.taskStatus = "id: " + taskID + ", status: active"; } else { - response.taskStatus = "id: " + taskUUID + ", status: inactive"; + response.taskStatus = "id: " + taskID + ", status: inactive"; } return response; 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 4f367aad1a0d..4b34f9d49261 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 @@ -53,7 +53,7 @@ public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throw List taskList = new ListActiveTasks(req).listAllActiveTasks().taskList; if (taskList != null) { for (ActiveTaskDetails task : taskList) { - tasks.add(task.taskUUID, task.taskQuery); + tasks.add(task.taskID, task.taskQuery); } } rsp.add("taskList", tasks); 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 index 7fb8114e0726..13c2789cdef5 100644 --- 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 @@ -75,8 +75,8 @@ public void testGetActiveTasks() throws Exception { assertEquals(2, response.taskList.size()); - assertEquals("taskID1", response.taskList.get(0).taskUUID); - assertEquals("/search?q=h&gf=text-1", response.taskList.get(0).taskQuery); + assertEquals("taskID1", response.taskList.getFirst().taskID); + assertEquals("/search?q=h&gf=text-1", response.taskList.getFirst().taskQuery); assertNull(response.error); } From 24ca810f9e7f09a34b973fd06e9bac166e1b61de Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Fri, 29 May 2026 02:41:45 +0530 Subject: [PATCH 26/70] comments addressed --- .../unreleased/SOLR-18248-list-tasks.yml | 1 + .../solr/client/api/endpoint/TasksApi.java | 33 ++++---- .../client/api/model/TaskStatusResponse.java | 14 +++- .../solr/handler/admin/api/GetTaskStatus.java | 48 ++++++++++++ .../handler/admin/api/ListActiveTasks.java | 21 +---- .../component/ActiveTasksListHandler.java | 19 +++-- .../handler/admin/api/GetTaskStatusTest.java | 77 +++++++++++++++++++ .../admin/api/ListActiveTasksTest.java | 25 ++---- 8 files changed, 175 insertions(+), 63 deletions(-) create mode 100644 solr/core/src/java/org/apache/solr/handler/admin/api/GetTaskStatus.java create mode 100644 solr/core/src/test/org/apache/solr/handler/admin/api/GetTaskStatusTest.java diff --git a/changelog/unreleased/SOLR-18248-list-tasks.yml b/changelog/unreleased/SOLR-18248-list-tasks.yml index 5e8df2c0b414..3dc9716c12c5 100644 --- a/changelog/unreleased/SOLR-18248-list-tasks.yml +++ b/changelog/unreleased/SOLR-18248-list-tasks.yml @@ -2,6 +2,7 @@ title: Migrated ListTasks API & TaskStatus API from homegrown @EndPoint to JAX-R type: added authors: - name: Jalaz Kumar + - name: Eric Pugh 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 1c9cb95e4193..c11126c30c13 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 @@ -27,21 +27,26 @@ import org.apache.solr.client.api.model.TaskStatusResponse; import org.apache.solr.client.api.util.StoreApiParameters; -@Path(INDEX_PATH_PREFIX + "/tasks") +@Path(INDEX_PATH_PREFIX) public interface TasksApi { - @GET - @StoreApiParameters - @Operation( - summary = "Lists all the currently running tasks", - tags = {"tasks"}) - ListActiveTaskResponse listAllActiveTasks() throws Exception; + @Path("/tasks") + interface List { + @GET + @StoreApiParameters + @Operation( + summary = "Lists all the currently running active tasks.", + tags = {"tasks"}) + ListActiveTaskResponse listAllActiveTasks() throws Exception; + } - @GET - @Path("/{taskID}") - @StoreApiParameters - @Operation( - summary = "Status of a specific taskUUID passed as pathParam", - tags = {"tasks"}) - TaskStatusResponse getTaskStatus(@PathParam("taskID") String taskID) throws Exception; + @Path("/tasks/{taskID}") + interface Status { + @GET + @StoreApiParameters + @Operation( + summary = "Status of a specific taskID passed as pathParam.", + tags = {"tasks"}) + TaskStatusResponse getTaskStatus(@PathParam("taskID") String taskID) throws Exception; + } } 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 index 6cae72670d7c..2b3692203d80 100644 --- 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 @@ -20,5 +20,17 @@ import com.fasterxml.jackson.annotation.JsonProperty; public class TaskStatusResponse extends SolrJerseyResponse { - @JsonProperty public String taskStatus; + + public enum TaskStatus { + ACTIVE("active"), + INACTIVE("inactive"); + + private final String value; + + TaskStatus(String value) { this.value = value; } + + public String getValue() { return this.value; } + } + + @JsonProperty public TaskStatus taskStatus; } 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..6b178da187db --- /dev/null +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/GetTaskStatus.java @@ -0,0 +1,48 @@ +/* + * 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 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.jersey.PermissionName; +import org.apache.solr.request.SolrQueryRequest; + +import static org.apache.solr.security.PermissionNameProvider.Name.READ_PERM; + +public class GetTaskStatus extends JerseyResource implements TasksApi.Status { + + private final SolrQueryRequest solrQueryRequest; + + 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 = + solrQueryRequest.getCore().getCancellableQueryTracker().isQueryIdActive(taskID); + + response.taskStatus = (isTaskActive) ? TaskStatusResponse.TaskStatus.ACTIVE : TaskStatusResponse.TaskStatus.INACTIVE; + + return response; + } +} 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 index c2becbcbd43e..56c4a1ba8a3f 100644 --- 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 @@ -28,11 +28,10 @@ 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.jersey.PermissionName; import org.apache.solr.request.SolrQueryRequest; -public class ListActiveTasks extends JerseyResource implements TasksApi { +public class ListActiveTasks extends JerseyResource implements TasksApi.List { private final SolrQueryRequest solrQueryRequest; @@ -45,25 +44,7 @@ public ListActiveTasks(SolrQueryRequest solrQueryRequest) { @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 taskID) throws Exception { - final TaskStatusResponse response = instantiateJerseyResponse(TaskStatusResponse.class); - - boolean isTaskActive = - solrQueryRequest.getCore().getCancellableQueryTracker().isQueryIdActive(taskID); - if (isTaskActive) { - response.taskStatus = "id: " + taskID + ", status: active"; - } else { - response.taskStatus = "id: " + taskID + ", status: inactive"; - } - return response; } 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 4b34f9d49261..52d268ad5f69 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 @@ -23,9 +23,10 @@ import org.apache.solr.api.Api; import org.apache.solr.api.JerseyResource; import org.apache.solr.client.api.model.ActiveTaskDetails; +import org.apache.solr.client.api.model.TaskStatusResponse; import org.apache.solr.common.util.NamedList; +import org.apache.solr.handler.admin.api.GetTaskStatus; 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; @@ -33,9 +34,9 @@ import org.apache.solr.security.PermissionNameProvider; /** - * 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. + * Handles request for listing the active cancellable tasks & Status check of any particular task, + * actual logic lives in the v2: {@link ListActiveTasks} & {@link GetTaskStatus}; + * this handler is a thin v1 bridge that extracts request parameters and delegates over to v2. */ public class ActiveTasksListHandler extends TaskManagementHandler { // This can be a parent level member but we keep it here to allow future handlers to have @@ -43,11 +44,13 @@ public class ActiveTasksListHandler extends TaskManagementHandler { @Override public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception { - String taskStatusCheckUUID = req.getParams().get(TASK_CHECK_UUID, null); + String taskStatusCheckID = req.getParams().get(TASK_CHECK_UUID, null); + + if (taskStatusCheckID != null) { + TaskStatusResponse taskStatusResponse = new GetTaskStatus(req).getTaskStatus(taskStatusCheckID); + String taskStatus = "id: " + taskStatusCheckID + ", status: " + taskStatusResponse.taskStatus.getValue(); + rsp.add("taskStatus", taskStatus); - if (taskStatusCheckUUID != null) { - V2ApiUtils.squashIntoSolrResponseWithoutHeader( - rsp, new ListActiveTasks(req).getTaskStatus(taskStatusCheckUUID)); } else { NamedList tasks = new NamedList<>(); List taskList = new ListActiveTasks(req).listAllActiveTasks().taskList; 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..b9b09a83dfa4 --- /dev/null +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/GetTaskStatusTest.java @@ -0,0 +1,77 @@ +/* + * 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 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; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +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 taskStatusResponse; + + taskStatusResponse = getTaskStatus.getTaskStatus("taskID_running"); + assertEquals(TaskStatusResponse.TaskStatus.ACTIVE, taskStatusResponse.taskStatus); + assertNull(taskStatusResponse.error); + + taskStatusResponse = getTaskStatus.getTaskStatus("taskID_stopped"); + assertEquals(TaskStatusResponse.TaskStatus.INACTIVE, taskStatusResponse.taskStatus); + assertNull(taskStatusResponse.error); + } + +} 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 index 13c2789cdef5..5c543baf97f1 100644 --- 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 @@ -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; @@ -75,26 +74,12 @@ public void testGetActiveTasks() throws Exception { assertEquals(2, response.taskList.size()); - assertEquals("taskID1", response.taskList.getFirst().taskID); - assertEquals("/search?q=h&gf=text-1", response.taskList.getFirst().taskQuery); + assertEquals("taskID1", response.taskList.get(0).taskID); + assertEquals("/search?q=h&gf=text-1", response.taskList.get(0).taskQuery); - assertNull(response.error); - } + assertEquals("taskID2", response.taskList.get(1).taskID); + assertEquals("/search?q=h&gf=text-2", response.taskList.get(1).taskQuery); - @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); + assertNull(response.error); } } From c583c386ffc0c4e12d488edef2474c01cc05dede Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Fri, 29 May 2026 02:45:16 +0530 Subject: [PATCH 27/70] tidying it up --- .../solr/client/api/model/TaskStatusResponse.java | 8 ++++++-- .../apache/solr/handler/admin/api/GetTaskStatus.java | 9 ++++++--- .../handler/component/ActiveTasksListHandler.java | 12 +++++++----- .../solr/handler/admin/api/GetTaskStatusTest.java | 8 +++----- 4 files changed, 22 insertions(+), 15 deletions(-) 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 index 2b3692203d80..16a0f89c53bf 100644 --- 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 @@ -27,9 +27,13 @@ public enum TaskStatus { private final String value; - TaskStatus(String value) { this.value = value; } + TaskStatus(String value) { + this.value = value; + } - public String getValue() { return this.value; } + public String getValue() { + return this.value; + } } @JsonProperty public TaskStatus taskStatus; 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 index 6b178da187db..6edef2d6f306 100644 --- 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 @@ -17,14 +17,14 @@ package org.apache.solr.handler.admin.api; +import static org.apache.solr.security.PermissionNameProvider.Name.READ_PERM; + 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.jersey.PermissionName; import org.apache.solr.request.SolrQueryRequest; -import static org.apache.solr.security.PermissionNameProvider.Name.READ_PERM; - public class GetTaskStatus extends JerseyResource implements TasksApi.Status { private final SolrQueryRequest solrQueryRequest; @@ -41,7 +41,10 @@ public TaskStatusResponse getTaskStatus(String taskID) throws Exception { boolean isTaskActive = solrQueryRequest.getCore().getCancellableQueryTracker().isQueryIdActive(taskID); - response.taskStatus = (isTaskActive) ? TaskStatusResponse.TaskStatus.ACTIVE : TaskStatusResponse.TaskStatus.INACTIVE; + response.taskStatus = + (isTaskActive) + ? TaskStatusResponse.TaskStatus.ACTIVE + : TaskStatusResponse.TaskStatus.INACTIVE; return response; } 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 52d268ad5f69..19ae609c50f9 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 @@ -34,9 +34,9 @@ import org.apache.solr.security.PermissionNameProvider; /** - * Handles request for listing the active cancellable tasks & Status check of any particular task, - * actual logic lives in the v2: {@link ListActiveTasks} & {@link GetTaskStatus}; - * this handler is a thin v1 bridge that extracts request parameters and delegates over to v2. + * Handles request for listing the active cancellable tasks and Status check of any particular task, + * actual logic lives in the v2: {@link ListActiveTasks} and {@link GetTaskStatus}; this handler is + * a thin v1 bridge that extracts request parameters and delegates over to v2. */ public class ActiveTasksListHandler extends TaskManagementHandler { // This can be a parent level member but we keep it here to allow future handlers to have @@ -47,8 +47,10 @@ public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throw String taskStatusCheckID = req.getParams().get(TASK_CHECK_UUID, null); if (taskStatusCheckID != null) { - TaskStatusResponse taskStatusResponse = new GetTaskStatus(req).getTaskStatus(taskStatusCheckID); - String taskStatus = "id: " + taskStatusCheckID + ", status: " + taskStatusResponse.taskStatus.getValue(); + TaskStatusResponse taskStatusResponse = + new GetTaskStatus(req).getTaskStatus(taskStatusCheckID); + String taskStatus = + "id: " + taskStatusCheckID + ", status: " + taskStatusResponse.taskStatus.getValue(); rsp.add("taskStatus", taskStatus); } else { 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 index b9b09a83dfa4..d824d6438e22 100644 --- 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 @@ -17,6 +17,9 @@ 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; @@ -26,9 +29,6 @@ import org.junit.BeforeClass; import org.junit.Test; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - public class GetTaskStatusTest extends SolrTestCaseJ4 { private SolrQueryRequest mockQueryRequest; @@ -37,7 +37,6 @@ public class GetTaskStatusTest extends SolrTestCaseJ4 { private GetTaskStatus getTaskStatus; - @BeforeClass public static void ensureWorkingMockito() { assumeWorkingMockito(); @@ -73,5 +72,4 @@ public void testGetTaskStatus() throws Exception { assertEquals(TaskStatusResponse.TaskStatus.INACTIVE, taskStatusResponse.taskStatus); assertNull(taskStatusResponse.error); } - } From bb0f0f147570ac4e536b37e9e2982c4ed9e31601 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Fri, 29 May 2026 08:17:10 +0530 Subject: [PATCH 28/70] comments addressed --- .../apache/solr/client/api/endpoint/TasksApi.java | 4 ++-- .../apache/solr/handler/admin/api/GetTaskStatus.java | 5 +++-- .../handler/component/ActiveTasksListHandler.java | 12 ++++++------ 3 files changed, 11 insertions(+), 10 deletions(-) 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 c11126c30c13..a706a00cfaba 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 @@ -35,7 +35,7 @@ interface List { @GET @StoreApiParameters @Operation( - summary = "Lists all the currently running active tasks.", + summary = "Lists all the active tasks.", tags = {"tasks"}) ListActiveTaskResponse listAllActiveTasks() throws Exception; } @@ -45,7 +45,7 @@ interface Status { @GET @StoreApiParameters @Operation( - summary = "Status of a specific taskID passed as pathParam.", + summary = "Status of a specific taskID.", 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 index 6edef2d6f306..e24a32949da3 100644 --- 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 @@ -17,6 +17,7 @@ package org.apache.solr.handler.admin.api; +import static org.apache.solr.client.api.model.TaskStatusResponse.TaskStatus; import static org.apache.solr.security.PermissionNameProvider.Name.READ_PERM; import org.apache.solr.api.JerseyResource; @@ -43,8 +44,8 @@ public TaskStatusResponse getTaskStatus(String taskID) throws Exception { response.taskStatus = (isTaskActive) - ? TaskStatusResponse.TaskStatus.ACTIVE - : TaskStatusResponse.TaskStatus.INACTIVE; + ? TaskStatus.ACTIVE + : TaskStatus.INACTIVE; return response; } 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 19ae609c50f9..839be5b41847 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 @@ -34,8 +34,8 @@ import org.apache.solr.security.PermissionNameProvider; /** - * Handles request for listing the active cancellable tasks and Status check of any particular task, - * actual logic lives in the v2: {@link ListActiveTasks} and {@link GetTaskStatus}; this handler is + * Handles request for listing all active cancellable tasks and get status check of any taskId. + * Actual logic lives in the v2: {@link ListActiveTasks} and {@link GetTaskStatus}; this handler is * a thin v1 bridge that extracts request parameters and delegates over to v2. */ public class ActiveTasksListHandler extends TaskManagementHandler { @@ -44,13 +44,13 @@ public class ActiveTasksListHandler extends TaskManagementHandler { @Override public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception { - String taskStatusCheckID = req.getParams().get(TASK_CHECK_UUID, null); + String taskStatusCheckUUID = req.getParams().get(TASK_CHECK_UUID, null); - if (taskStatusCheckID != null) { + if (taskStatusCheckUUID != null) { TaskStatusResponse taskStatusResponse = - new GetTaskStatus(req).getTaskStatus(taskStatusCheckID); + new GetTaskStatus(req).getTaskStatus(taskStatusCheckUUID); String taskStatus = - "id: " + taskStatusCheckID + ", status: " + taskStatusResponse.taskStatus.getValue(); + "id: " + taskStatusCheckUUID + ", status: " + taskStatusResponse.taskStatus.getValue(); rsp.add("taskStatus", taskStatus); } else { From d0ddec6dfb76597d324f410e5f5cf0ce91d19ddb Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Fri, 29 May 2026 08:17:57 +0530 Subject: [PATCH 29/70] tidy up --- .../org/apache/solr/handler/admin/api/GetTaskStatus.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) 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 index e24a32949da3..98c77028158f 100644 --- 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 @@ -42,10 +42,7 @@ public TaskStatusResponse getTaskStatus(String taskID) throws Exception { boolean isTaskActive = solrQueryRequest.getCore().getCancellableQueryTracker().isQueryIdActive(taskID); - response.taskStatus = - (isTaskActive) - ? TaskStatus.ACTIVE - : TaskStatus.INACTIVE; + response.taskStatus = (isTaskActive) ? TaskStatus.ACTIVE : TaskStatus.INACTIVE; return response; } From 09052026d7012722ece4a6768b5c8c6c28841a8a Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Fri, 29 May 2026 08:22:57 +0530 Subject: [PATCH 30/70] update --- .../src/java/org/apache/solr/client/api/endpoint/TasksApi.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 a706a00cfaba..30dce7597918 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 @@ -45,7 +45,7 @@ interface Status { @GET @StoreApiParameters @Operation( - summary = "Status of a specific taskID.", + summary = "Status of a specific task.", tags = {"tasks"}) TaskStatusResponse getTaskStatus(@PathParam("taskID") String taskID) throws Exception; } From d08d788075a6ff987e1baebaef6e3c7c0dc4b390 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Fri, 29 May 2026 09:22:04 +0530 Subject: [PATCH 31/70] minor --- .../src/java/org/apache/solr/client/api/endpoint/TasksApi.java | 2 +- .../java/org/apache/solr/handler/admin/api/GetTaskStatus.java | 2 ++ .../apache/solr/handler/component/ActiveTasksListHandler.java | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) 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 30dce7597918..12d1ae0d3ef3 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 @@ -27,7 +27,7 @@ import org.apache.solr.client.api.model.TaskStatusResponse; import org.apache.solr.client.api.util.StoreApiParameters; -@Path(INDEX_PATH_PREFIX) +@Path(INDEX_PATH_PREFIX + "/tasks") public interface TasksApi { @Path("/tasks") 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 index 98c77028158f..95ca04837b9d 100644 --- 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 @@ -20,6 +20,7 @@ import static org.apache.solr.client.api.model.TaskStatusResponse.TaskStatus; 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; @@ -30,6 +31,7 @@ public class GetTaskStatus extends JerseyResource implements TasksApi.Status { private final SolrQueryRequest solrQueryRequest; + @Inject public GetTaskStatus(SolrQueryRequest solrQueryRequest) { this.solrQueryRequest = solrQueryRequest; } 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 839be5b41847..c64fc1669bb2 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 @@ -102,6 +102,6 @@ public Collection getApis() { @Override public Collection> getJerseyResources() { - return List.of(ListActiveTasks.class); + return List.of(ListActiveTasks.class, GetTaskStatus.class); } } From 1b0b81da66d503668ee83fa88ef23e543c725bd4 Mon Sep 17 00:00:00 2001 From: Eric Pugh Date: Fri, 29 May 2026 07:48:51 -0400 Subject: [PATCH 32/70] Remove "breadcrumb" pointer, we only do it in one other place. Turns out I started this pattern, but it's not actually a pattern we want to support! So backing it out of the two places that have it. --- .../org/apache/solr/handler/admin/HealthCheckHandler.java | 3 --- .../solr/handler/component/ActiveTasksListHandler.java | 6 +----- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/handler/admin/HealthCheckHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/HealthCheckHandler.java index 1dab5d1d9778..8c73ac11af3b 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/HealthCheckHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/HealthCheckHandler.java @@ -59,9 +59,6 @@ * specify the acceptable generation lag follower should be with respect to its leader using the * maxGenerationLag=<max_generation_lag> request parameter. If * maxGenerationLag is not provided then health check would simply return OK. - * - *

All health-check logic lives in the v2 {@link NodeHealth}; this handler is a thin v1 bridge - * that extracts request parameters and delegates. */ public class HealthCheckHandler extends RequestHandlerBase { 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 c64fc1669bb2..2cd5e3857a45 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 @@ -33,11 +33,7 @@ import org.apache.solr.security.AuthorizationContext; import org.apache.solr.security.PermissionNameProvider; -/** - * Handles request for listing all active cancellable tasks and get status check of any taskId. - * Actual logic lives in the v2: {@link ListActiveTasks} and {@link GetTaskStatus}; this handler is - * a thin v1 bridge that extracts request parameters and delegates over to v2. - */ +/** Handles request for listing all active cancellable tasks and get status check of any taskId. */ 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 From 200afbaeb67adc97993462b5d45cdaec7f79f0b5 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 30 May 2026 02:47:17 +0530 Subject: [PATCH 33/70] checking --- .../java/org/apache/solr/client/api/endpoint/TasksApi.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 12d1ae0d3ef3..ff2762dbf5c4 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,7 +30,7 @@ @Path(INDEX_PATH_PREFIX + "/tasks") public interface TasksApi { - @Path("/tasks") + @Path("") interface List { @GET @StoreApiParameters @@ -40,7 +40,7 @@ interface List { ListActiveTaskResponse listAllActiveTasks() throws Exception; } - @Path("/tasks/{taskID}") + @Path("{taskID}") interface Status { @GET @StoreApiParameters From d1614855dbdbf1c970bd304092568e1d7555a6e2 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Wed, 3 Jun 2026 01:14:59 +0530 Subject: [PATCH 34/70] this works --- .../solr/client/api/endpoint/TasksApi.java | 31 ++++------ .../solr/handler/admin/api/ActiveTask.java | 61 +++++++++++++++++++ 2 files changed, 74 insertions(+), 18 deletions(-) create mode 100644 solr/core/src/java/org/apache/solr/handler/admin/api/ActiveTask.java 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 ff2762dbf5c4..98061204eebf 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,23 +30,18 @@ @Path(INDEX_PATH_PREFIX + "/tasks") public interface TasksApi { - @Path("") - interface List { - @GET - @StoreApiParameters - @Operation( - summary = "Lists all the active tasks.", - tags = {"tasks"}) - ListActiveTaskResponse listAllActiveTasks() throws Exception; - } + @GET + @StoreApiParameters + @Operation( + summary = "Lists all the currently running tasks", + tags = {"tasks"}) + ListActiveTaskResponse listAllActiveTasks() throws Exception; - @Path("{taskID}") - interface Status { - @GET - @StoreApiParameters - @Operation( - summary = "Status of a specific task.", - tags = {"tasks"}) - TaskStatusResponse getTaskStatus(@PathParam("taskID") String taskID) throws Exception; - } + @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/core/src/java/org/apache/solr/handler/admin/api/ActiveTask.java b/solr/core/src/java/org/apache/solr/handler/admin/api/ActiveTask.java new file mode 100644 index 000000000000..3b02b6eba3b6 --- /dev/null +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/ActiveTask.java @@ -0,0 +1,61 @@ +package org.apache.solr.handler.admin.api; + +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.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; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import static org.apache.solr.security.PermissionNameProvider.Name.READ_PERM; + +public class ActiveTask extends JerseyResource implements TasksApi { + + private final SolrQueryRequest solrQueryRequest; + + @Inject + public ActiveTask(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 taskID) throws Exception { + final TaskStatusResponse response = instantiateJerseyResponse(TaskStatusResponse.class); + + boolean isTaskActive = + solrQueryRequest.getCore().getCancellableQueryTracker().isQueryIdActive(taskID); + + response.taskStatus = (isTaskActive) ? TaskStatusResponse.TaskStatus.ACTIVE : TaskStatusResponse.TaskStatus.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; + } + +} From 12e0a9c27a68f2e66b27f00c6fdb70e7934d3811 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Wed, 3 Jun 2026 01:15:40 +0530 Subject: [PATCH 35/70] commenting the remaining code & related tests for now --- .../solr/handler/admin/api/GetTaskStatus.java | 44 ++++----- .../handler/admin/api/ListActiveTasks.java | 60 ++++++------ .../component/ActiveTasksListHandler.java | 12 ++- .../handler/admin/api/GetTaskStatusTest.java | 82 ++++++++-------- .../admin/api/ListActiveTasksTest.java | 96 +++++++++---------- 5 files changed, 148 insertions(+), 146 deletions(-) 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 index 95ca04837b9d..4819fd7f95c5 100644 --- 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 @@ -27,25 +27,25 @@ 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 = - solrQueryRequest.getCore().getCancellableQueryTracker().isQueryIdActive(taskID); - - response.taskStatus = (isTaskActive) ? TaskStatus.ACTIVE : TaskStatus.INACTIVE; - - return response; - } -} +//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 = +// solrQueryRequest.getCore().getCancellableQueryTracker().isQueryIdActive(taskID); +// +// response.taskStatus = (isTaskActive) ? TaskStatus.ACTIVE : TaskStatus.INACTIVE; +// +// return response; +// } +//} 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 index 56c4a1ba8a3f..ed65a644e056 100644 --- 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 @@ -31,33 +31,33 @@ import org.apache.solr.jersey.PermissionName; import org.apache.solr.request.SolrQueryRequest; -public class ListActiveTasks extends JerseyResource implements TasksApi.List { - - 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; - } - - 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; - } -} +//public class ListActiveTasks extends JerseyResource implements TasksApi.List { + +// 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; +// } +// +// 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/component/ActiveTasksListHandler.java b/solr/core/src/java/org/apache/solr/handler/component/ActiveTasksListHandler.java index 2cd5e3857a45..77fe7bb59d3a 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 @@ -25,8 +25,9 @@ import org.apache.solr.client.api.model.ActiveTaskDetails; import org.apache.solr.client.api.model.TaskStatusResponse; import org.apache.solr.common.util.NamedList; -import org.apache.solr.handler.admin.api.GetTaskStatus; -import org.apache.solr.handler.admin.api.ListActiveTasks; +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; @@ -44,14 +45,14 @@ public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throw if (taskStatusCheckUUID != null) { TaskStatusResponse taskStatusResponse = - new GetTaskStatus(req).getTaskStatus(taskStatusCheckUUID); + new ActiveTask(req).getTaskStatus(taskStatusCheckUUID); String taskStatus = "id: " + taskStatusCheckUUID + ", status: " + taskStatusResponse.taskStatus.getValue(); rsp.add("taskStatus", taskStatus); } else { NamedList tasks = new NamedList<>(); - List taskList = new ListActiveTasks(req).listAllActiveTasks().taskList; + List taskList = new ActiveTask(req).listAllActiveTasks().taskList; if (taskList != null) { for (ActiveTaskDetails task : taskList) { tasks.add(task.taskID, task.taskQuery); @@ -98,6 +99,7 @@ public Collection getApis() { @Override public Collection> getJerseyResources() { - return List.of(ListActiveTasks.class, GetTaskStatus.class); +// return List.of(ListActiveTasks.class, GetTaskStatus.class); + return List.of(ActiveTask.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 index d824d6438e22..9ea347190b1e 100644 --- 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 @@ -31,45 +31,45 @@ 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 taskStatusResponse; - - taskStatusResponse = getTaskStatus.getTaskStatus("taskID_running"); - assertEquals(TaskStatusResponse.TaskStatus.ACTIVE, taskStatusResponse.taskStatus); - assertNull(taskStatusResponse.error); - - taskStatusResponse = getTaskStatus.getTaskStatus("taskID_stopped"); - assertEquals(TaskStatusResponse.TaskStatus.INACTIVE, taskStatusResponse.taskStatus); - assertNull(taskStatusResponse.error); - } +// private SolrQueryRequest mockQueryRequest; +// private SolrCore solrCore; +// private CancellableQueryTracker cancellableQueryTracker; +// +// private GetTaskStatus.java 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.java(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 taskStatusResponse; +// +// taskStatusResponse = getTaskStatus.getTaskStatus("taskID_running"); +// assertEquals(TaskStatusResponse.TaskStatus.ACTIVE, taskStatusResponse.taskStatus); +// assertNull(taskStatusResponse.error); +// +// taskStatusResponse = getTaskStatus.getTaskStatus("taskID_stopped"); +// assertEquals(TaskStatusResponse.TaskStatus.INACTIVE, taskStatusResponse.taskStatus); +// assertNull(taskStatusResponse.error); +// } } 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 index 5c543baf97f1..f7c89e174a81 100644 --- 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 @@ -34,52 +34,52 @@ 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).taskID); - assertEquals("/search?q=h&gf=text-1", response.taskList.get(0).taskQuery); - - assertEquals("taskID2", response.taskList.get(1).taskID); - assertEquals("/search?q=h&gf=text-2", response.taskList.get(1).taskQuery); - - assertNull(response.error); - } +// 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).taskID); +// assertEquals("/search?q=h&gf=text-1", response.taskList.get(0).taskQuery); +// +// assertEquals("taskID2", response.taskList.get(1).taskID); +// assertEquals("/search?q=h&gf=text-2", response.taskList.get(1).taskQuery); +// +// assertNull(response.error); +// } } From 6c3ed49c9846be8cc82d907a33a6409151a3bc4e Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Mon, 15 Jun 2026 00:41:35 +0530 Subject: [PATCH 36/70] removed commented code --- .../solr/handler/admin/api/GetTaskStatus.java | 51 ----------- .../handler/admin/api/ListActiveTasks.java | 63 -------------- .../component/ActiveTasksListHandler.java | 3 - .../handler/admin/api/GetTaskStatusTest.java | 75 ---------------- .../admin/api/ListActiveTasksTest.java | 85 ------------------- 5 files changed, 277 deletions(-) delete mode 100644 solr/core/src/java/org/apache/solr/handler/admin/api/GetTaskStatus.java delete mode 100644 solr/core/src/java/org/apache/solr/handler/admin/api/ListActiveTasks.java delete mode 100644 solr/core/src/test/org/apache/solr/handler/admin/api/GetTaskStatusTest.java delete mode 100644 solr/core/src/test/org/apache/solr/handler/admin/api/ListActiveTasksTest.java 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 deleted file mode 100644 index 4819fd7f95c5..000000000000 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/GetTaskStatus.java +++ /dev/null @@ -1,51 +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.api.model.TaskStatusResponse.TaskStatus; -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.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 = -// solrQueryRequest.getCore().getCancellableQueryTracker().isQueryIdActive(taskID); -// -// response.taskStatus = (isTaskActive) ? TaskStatus.ACTIVE : TaskStatus.INACTIVE; -// -// return response; -// } -//} 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 deleted file mode 100644 index ed65a644e056..000000000000 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/ListActiveTasks.java +++ /dev/null @@ -1,63 +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.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.TasksApi; -import org.apache.solr.client.api.model.ActiveTaskDetails; -import org.apache.solr.client.api.model.ListActiveTaskResponse; -import org.apache.solr.jersey.PermissionName; -import org.apache.solr.request.SolrQueryRequest; - -//public class ListActiveTasks extends JerseyResource implements TasksApi.List { - -// 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; -// } -// -// 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/component/ActiveTasksListHandler.java b/solr/core/src/java/org/apache/solr/handler/component/ActiveTasksListHandler.java index 77fe7bb59d3a..8f9937c0dd0e 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,8 +26,6 @@ import org.apache.solr.client.api.model.TaskStatusResponse; import org.apache.solr.common.util.NamedList; 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; @@ -99,7 +97,6 @@ public Collection getApis() { @Override public Collection> getJerseyResources() { -// return List.of(ListActiveTasks.class, GetTaskStatus.class); return List.of(ActiveTask.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 deleted file mode 100644 index 9ea347190b1e..000000000000 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/GetTaskStatusTest.java +++ /dev/null @@ -1,75 +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.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.java 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.java(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 taskStatusResponse; -// -// taskStatusResponse = getTaskStatus.getTaskStatus("taskID_running"); -// assertEquals(TaskStatusResponse.TaskStatus.ACTIVE, taskStatusResponse.taskStatus); -// assertNull(taskStatusResponse.error); -// -// taskStatusResponse = getTaskStatus.getTaskStatus("taskID_stopped"); -// assertEquals(TaskStatusResponse.TaskStatus.INACTIVE, taskStatusResponse.taskStatus); -// assertNull(taskStatusResponse.error); -// } -} 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 deleted file mode 100644 index f7c89e174a81..000000000000 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/ListActiveTasksTest.java +++ /dev/null @@ -1,85 +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.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.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).taskID); -// assertEquals("/search?q=h&gf=text-1", response.taskList.get(0).taskQuery); -// -// assertEquals("taskID2", response.taskList.get(1).taskID); -// assertEquals("/search?q=h&gf=text-2", response.taskList.get(1).taskQuery); -// -// assertNull(response.error); -// } -} From 1a6c5e3b9f6a5442ee9ffb64b33e3631bdd3d334 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Mon, 15 Jun 2026 00:58:04 +0530 Subject: [PATCH 37/70] pr ready again --- .../solr/client/api/endpoint/TasksApi.java | 8 +- .../handler/admin/api/ActiveTaskTest.java | 100 ++++++++++++++++++ 2 files changed, 104 insertions(+), 4 deletions(-) create mode 100644 solr/core/src/test/org/apache/solr/handler/admin/api/ActiveTaskTest.java 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 98061204eebf..3e46c1465c64 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 @@ -33,15 +33,15 @@ public interface TasksApi { @GET @StoreApiParameters @Operation( - summary = "Lists all the currently running tasks", + summary = "Lists all the active tasks", tags = {"tasks"}) ListActiveTaskResponse listAllActiveTasks() throws Exception; @GET - @Path("/{taskUUID}") + @Path("/{taskID}") @StoreApiParameters @Operation( - summary = "Status of a specific taskUUID passed as pathParam", + summary = "Status of a specific task", tags = {"tasks"}) - TaskStatusResponse getTaskStatus(@PathParam("taskUUID") String taskUUID) throws Exception; + TaskStatusResponse getTaskStatus(@PathParam("taskID") String taskID) throws Exception; } 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/ActiveTaskTest.java new file mode 100644 index 000000000000..7ce01936abbb --- /dev/null +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/ActiveTaskTest.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 ActiveTaskTest extends SolrTestCaseJ4 { + + private SolrQueryRequest mockQueryRequest; + private SolrCore solrCore; + private CancellableQueryTracker cancellableQueryTracker; + + private ActiveTask activeTask; + + @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); + + activeTask = new ActiveTask(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 = activeTask.listAllActiveTasks(); + assertNotNull(response.taskList); + + assertEquals(2, response.taskList.size()); + + assertEquals("taskID1", response.taskList.get(0).taskID); + 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 = activeTask.getTaskStatus("taskID_running"); + assertEquals(TaskStatusResponse.TaskStatus.ACTIVE, responseRunningTask.taskStatus); + assertNull(responseRunningTask.error); + + TaskStatusResponse responseStoppedTask = activeTask.getTaskStatus("taskID_stopped"); + assertEquals(TaskStatusResponse.TaskStatus.INACTIVE, responseStoppedTask.taskStatus); + assertNull(responseStoppedTask.error); + } +} From 4b16add7f292b14154616d4cf7c2009fe1cf30cb Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Mon, 15 Jun 2026 01:03:53 +0530 Subject: [PATCH 38/70] tidy up --- .../apache/solr/handler/admin/api/ActiveTask.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) 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/ActiveTask.java index 3b02b6eba3b6..f21bea6e74fe 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/ActiveTask.java @@ -1,6 +1,12 @@ 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.TasksApi; import org.apache.solr.client.api.model.ActiveTaskDetails; @@ -8,12 +14,6 @@ import org.apache.solr.client.api.model.TaskStatusResponse; import org.apache.solr.jersey.PermissionName; import org.apache.solr.request.SolrQueryRequest; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import static org.apache.solr.security.PermissionNameProvider.Name.READ_PERM; public class ActiveTask extends JerseyResource implements TasksApi { @@ -57,5 +57,4 @@ private List extractActiveTaskLists() { return activeTaskDetails; } - } From 96ad4f49a11998b0788f142c11efb0ed4a7ff0a7 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Mon, 15 Jun 2026 01:05:37 +0530 Subject: [PATCH 39/70] added license --- .../solr/handler/admin/api/ActiveTask.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) 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/ActiveTask.java index f21bea6e74fe..588518d90aa6 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/ActiveTask.java @@ -1,3 +1,20 @@ +/* + * 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; From 6133beb66ea0e9b74f9589a2ebe68481cc346396 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Mon, 15 Jun 2026 01:27:44 +0530 Subject: [PATCH 40/70] tidy forced --- .../java/org/apache/solr/handler/admin/api/ActiveTask.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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/ActiveTask.java index 588518d90aa6..91845608fcff 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/ActiveTask.java @@ -57,7 +57,10 @@ public TaskStatusResponse getTaskStatus(String taskID) throws Exception { boolean isTaskActive = solrQueryRequest.getCore().getCancellableQueryTracker().isQueryIdActive(taskID); - response.taskStatus = (isTaskActive) ? TaskStatusResponse.TaskStatus.ACTIVE : TaskStatusResponse.TaskStatus.INACTIVE; + response.taskStatus = + (isTaskActive) + ? TaskStatusResponse.TaskStatus.ACTIVE + : TaskStatusResponse.TaskStatus.INACTIVE; return response; } From c85327f44d00704cdff5b9dd44e204d33780c730 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Fri, 19 Jun 2026 00:34:10 +0530 Subject: [PATCH 41/70] fixed response format v1-list api --- .../apache/solr/handler/component/ActiveTasksListHandler.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 8f9937c0dd0e..320aabf5bd2b 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 @@ -25,6 +25,7 @@ import org.apache.solr.client.api.model.ActiveTaskDetails; import org.apache.solr.client.api.model.TaskStatusResponse; 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.request.SolrQueryRequest; import org.apache.solr.request.SolrRequestHandler; @@ -49,7 +50,7 @@ public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throw rsp.add("taskStatus", taskStatus); } else { - NamedList tasks = new NamedList<>(); + NamedList tasks = new SimpleOrderedMap<>(); List taskList = new ActiveTask(req).listAllActiveTasks().taskList; if (taskList != null) { for (ActiveTaskDetails task : taskList) { From e128b415f9636cd5ee11edfa2ce42aec0caadb11 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Fri, 19 Jun 2026 00:42:50 +0530 Subject: [PATCH 42/70] changes in response of v1 api --- .../apache/solr/handler/component/ActiveTasksListHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 320aabf5bd2b..b990c0c1ef86 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 @@ -16,6 +16,7 @@ */ package org.apache.solr.handler.component; +import static org.apache.solr.client.api.model.TaskStatusResponse.TaskStatus.ACTIVE; import static org.apache.solr.common.params.CommonParams.TASK_CHECK_UUID; import java.util.Collection; @@ -45,8 +46,7 @@ public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throw if (taskStatusCheckUUID != null) { TaskStatusResponse taskStatusResponse = new ActiveTask(req).getTaskStatus(taskStatusCheckUUID); - String taskStatus = - "id: " + taskStatusCheckUUID + ", status: " + taskStatusResponse.taskStatus.getValue(); + boolean taskStatus = taskStatusResponse.taskStatus.equals(ACTIVE); rsp.add("taskStatus", taskStatus); } else { From 1646d49df93f93856cd6c7388eb6f6160df73b5f Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 22 Aug 2026 22:40:58 +0530 Subject: [PATCH 43/70] cl --- .../unreleased/SOLR-18248-cancel-tasks.yml | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 changelog/unreleased/SOLR-18248-cancel-tasks.yml diff --git a/changelog/unreleased/SOLR-18248-cancel-tasks.yml b/changelog/unreleased/SOLR-18248-cancel-tasks.yml new file mode 100644 index 000000000000..adbdd558f46e --- /dev/null +++ b/changelog/unreleased/SOLR-18248-cancel-tasks.yml @@ -0,0 +1,32 @@ +# (DELETE ALL COMMENTS UP HERE AFTER FILLING THIS IN + +# See https://github.com/apache/solr/blob/main/dev-docs/changelog.adoc + +# If the change is minor, don't bother adding a changelog entry. +# For `other` type entries, the threshold to bother with a changelog entry should be even higher. + +# title: +# * The audience is end-users and administrators, not committers. +# * Be short and focused on the user impact. Multiple sentences is fine! +# * For technical/geeky details, prefer the commit message instead of changelog. +# * Reference JIRA issues like `SOLR-12345`, or if no JIRA but have a GitHub PR then `PR#12345`. + +# type: +# `added` for new features/improvements, opt-in by the user typically documented in the ref guide +# `changed` for improvements; not opt-in +# `fixed` for improvements that are deemed to have fixed buggy behavior +# `deprecated` for marking things deprecated +# `removed` for code removed +# `dependency_update` for updates to dependencies +# `other` for anything else, like large/significant refactorings, build changes, +# test infrastructure, or documentation. +# Most such changes are too small/minor to bother with a changelog entry. + +title: + Migration of CancelTask V2 API to JAX-RS construct +type: changed +authors: + - name: jaykay12 +links: + - name: SOLR-18248 + url: https://issues.apache.org/jira/browse/SOLR-18248 From 035875e2f6630ca9be847374ae0098ea4b529144 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Tue, 25 Aug 2026 03:21:53 +0530 Subject: [PATCH 44/70] cl --- .../unreleased/SOLR-18248-cancel-tasks.yml | 26 +------------------ 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/changelog/unreleased/SOLR-18248-cancel-tasks.yml b/changelog/unreleased/SOLR-18248-cancel-tasks.yml index adbdd558f46e..776891343a0d 100644 --- a/changelog/unreleased/SOLR-18248-cancel-tasks.yml +++ b/changelog/unreleased/SOLR-18248-cancel-tasks.yml @@ -1,32 +1,8 @@ -# (DELETE ALL COMMENTS UP HERE AFTER FILLING THIS IN - -# See https://github.com/apache/solr/blob/main/dev-docs/changelog.adoc - -# If the change is minor, don't bother adding a changelog entry. -# For `other` type entries, the threshold to bother with a changelog entry should be even higher. - -# title: -# * The audience is end-users and administrators, not committers. -# * Be short and focused on the user impact. Multiple sentences is fine! -# * For technical/geeky details, prefer the commit message instead of changelog. -# * Reference JIRA issues like `SOLR-12345`, or if no JIRA but have a GitHub PR then `PR#12345`. - -# type: -# `added` for new features/improvements, opt-in by the user typically documented in the ref guide -# `changed` for improvements; not opt-in -# `fixed` for improvements that are deemed to have fixed buggy behavior -# `deprecated` for marking things deprecated -# `removed` for code removed -# `dependency_update` for updates to dependencies -# `other` for anything else, like large/significant refactorings, build changes, -# test infrastructure, or documentation. -# Most such changes are too small/minor to bother with a changelog entry. - title: Migration of CancelTask V2 API to JAX-RS construct type: changed authors: - - name: jaykay12 + - name: Jalaz Kumar links: - name: SOLR-18248 url: https://issues.apache.org/jira/browse/SOLR-18248 From a0843da2c81be1a4ffa32456435bf3f76d621459 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Tue, 25 Aug 2026 03:25:12 +0530 Subject: [PATCH 45/70] contract --- .../org/apache/solr/client/api/endpoint/TasksApi.java | 11 +++++++++++ 1 file changed, 11 insertions(+) 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 46d80de5d9d3..28fa3b9946ef 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 @@ -20,6 +20,7 @@ import static org.apache.solr.client.api.util.Constants.INDEX_PATH_PREFIX; import io.swagger.v3.oas.annotations.Operation; +import jakarta.ws.rs.DELETE; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.ws.rs.PathParam; @@ -48,4 +49,14 @@ interface Status { tags = {"tasks"}) TaskStatusResponse getTaskStatus(@PathParam("taskID") String taskID) throws Exception; } + + @Path(INDEX_PATH_PREFIX + "/tasks/{taskID}") + interface Cancel { + @DELETE + @StoreApiParameters + @Operation( + summary = "Cancel any specific task", + tags = {"tasks"}) + TaskStatusResponse cancelRunningTask(@PathParam("taskID") String taskID) throws Exception; + } } From a8a5e1de94e94e0740347bd2cfb5f80507e72e9c Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 29 Aug 2026 23:37:33 +0530 Subject: [PATCH 46/70] changes --- .../client/api/model/CancelTaskResponse.java | 10 ++ .../solr/handler/admin/api/CancelTask.java | 13 +++ .../solr/handler/admin/api/CancelTaskAPI.java | 48 -------- .../component/ActiveTaskQuerySupport.java | 14 +++ .../component/QueryCancellationComponent.java | 108 ------------------ ...dler.java => TaskCancellationHandler.java} | 46 +++----- .../component/TaskManagementHandler.java | 3 - .../org/apache/solr/core/SolrCoreTest.java | 2 +- 8 files changed, 55 insertions(+), 189 deletions(-) create mode 100644 solr/api/src/java/org/apache/solr/client/api/model/CancelTaskResponse.java create mode 100644 solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java delete mode 100644 solr/core/src/java/org/apache/solr/handler/admin/api/CancelTaskAPI.java delete mode 100644 solr/core/src/java/org/apache/solr/handler/component/QueryCancellationComponent.java rename solr/core/src/java/org/apache/solr/handler/component/{QueryCancellationHandler.java => TaskCancellationHandler.java} (68%) diff --git a/solr/api/src/java/org/apache/solr/client/api/model/CancelTaskResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/CancelTaskResponse.java new file mode 100644 index 000000000000..76707a10d86b --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/CancelTaskResponse.java @@ -0,0 +1,10 @@ +package org.apache.solr.client.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class CancelTaskResponse { + + @JsonProperty + public CancelTaskResponse.TaskStatus status; + +} diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java b/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java new file mode 100644 index 000000000000..a1f0e91e94ef --- /dev/null +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java @@ -0,0 +1,13 @@ +package org.apache.solr.handler.admin.api; + +import org.apache.solr.api.JerseyResource; +import org.apache.solr.client.api.endpoint.TasksApi; +import org.apache.solr.client.api.model.TaskStatusResponse; + +public class CancelTask extends JerseyResource implements TasksApi.Cancel { + + @Override + public TaskStatusResponse cancelRunningTask(String taskID) throws Exception { + return null; + } +} diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTaskAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTaskAPI.java deleted file mode 100644 index a63adc055f42..000000000000 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTaskAPI.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.QueryCancellationHandler; -import org.apache.solr.request.SolrQueryRequest; -import org.apache.solr.response.SolrQueryResponse; -import org.apache.solr.security.PermissionNameProvider; - -/** - * V2 API for cancelling a currently running "task". - * - *

This API (GET /v2/collections/collectionName/tasks/cancel) is analogous to the v1 - * /solr/collectionName/tasks/cancel API. - */ -public class CancelTaskAPI { - private final QueryCancellationHandler cancellationHandler; - - public CancelTaskAPI(QueryCancellationHandler cancellationHandler) { - this.cancellationHandler = cancellationHandler; - } - - @EndPoint( - path = {"/tasks/cancel"}, - method = GET, - permission = PermissionNameProvider.Name.READ_PERM) - public void cancelActiveTask(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception { - cancellationHandler.handleRequestBody(req, rsp); - } -} 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 6276b419451f..d32daa5f7dd1 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 @@ -32,6 +32,7 @@ import org.apache.solr.handler.admin.api.ListActiveTasks; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.response.SolrQueryResponse; +import org.apache.solr.search.CancellableCollector; public class ActiveTaskQuerySupport { private static final String ACTIVE_TASK_LIST_HANDLER_PATH = "/tasks/list"; @@ -46,6 +47,10 @@ public static boolean isTaskActive(SolrQueryRequest req, String taskId) throws E return execute(req, taskId).taskActive; } + public static boolean cancelTask(SolrQueryRequest req, String taskId) throws Exception { + return cancel(req, taskId); + } + private static TaskQueryResult execute(SolrQueryRequest req, String taskId) throws Exception { if (!shouldDistributed(req)) { return localResult(req, taskId); @@ -53,6 +58,15 @@ private static TaskQueryResult execute(SolrQueryRequest req, String taskId) thro return distributedResult(req, taskId); } + private static boolean cancel(SolrQueryRequest req, String taskId) { + CancellableCollector cancellableTask = req.getCore().getCancellableQueryTracker().getCancellableTask(taskId); + if (cancellableTask != null) { + cancellableTask.cancel(); + return true; + } + return false; + } + private static TaskQueryResult localResult(SolrQueryRequest req, String taskId) { if (taskId != null) { return new TaskQueryResult(List.of(), ListActiveTasks.isTaskActiveOnThisShard(req, taskId)); diff --git a/solr/core/src/java/org/apache/solr/handler/component/QueryCancellationComponent.java b/solr/core/src/java/org/apache/solr/handler/component/QueryCancellationComponent.java deleted file mode 100644 index 9648bb312e44..000000000000 --- a/solr/core/src/java/org/apache/solr/handler/component/QueryCancellationComponent.java +++ /dev/null @@ -1,108 +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 org.apache.solr.search.CancellableCollector; - -/** Responsible for handling query cancellation requests */ -public class QueryCancellationComponent extends SearchComponent { - public static final String COMPONENT_NAME = "querycancellation"; - - private boolean shouldProcess; - - @Override - public void prepare(ResponseBuilder rb) throws IOException { - if (rb.isCancellation()) { - shouldProcess = true; - } - } - - @Override - public void process(ResponseBuilder rb) { - if (!shouldProcess) { - return; - } - - String cancellationUUID = rb.getCancellationUUID(); - - if (cancellationUUID == null) { - throw new RuntimeException("Null query UUID seen"); - } - - CancellableCollector cancellableTask = - rb.req.getCore().getCancellableQueryTracker().getCancellableTask(cancellationUUID); - - if (cancellableTask != null) { - cancellableTask.cancel(); - rb.rsp.add("cancellationResult", "success"); - } else { - rb.rsp.add("cancellationResult", "not found"); - } - } - - @Override - @SuppressWarnings("unchecked") - public void handleResponses(ResponseBuilder rb, ShardRequest sreq) { - if (!shouldProcess) { - return; - } - - boolean queryFound = false; - - for (ShardResponse r : sreq.responses) { - - String cancellationResult = - (String) r.getSolrResponse().getResponse().get("cancellationResult"); - - if (cancellationResult.equalsIgnoreCase("success")) { - queryFound = true; - - break; - } - } - - // If any shard sees the query as present, then we mark the query as successfully cancelled. If - // no shard found the query, then that can denote that the query was not found. This is - // important since the query cancellation request is broadcast to all shards, and the query - // might have completed on some shards but not on others - - if (queryFound) { - rb.rsp - .getValues() - .add( - "status", - "Query with queryID " + rb.getCancellationUUID() + " cancelled successfully"); - rb.rsp.getValues().add("responseCode", 200 /* HTTP OK */); - } else { - rb.rsp - .getValues() - .add("status", "Query with queryID " + rb.getCancellationUUID() + " not found"); - rb.rsp.getValues().add("responseCode", 404 /* HTTP NOT FOUND */); - } - } - - @Override - public String getDescription() { - return "Supports cancellation of queries which are cancellable"; - } - - @Override - public Category getCategory() { - return Category.OTHER; - } -} diff --git a/solr/core/src/java/org/apache/solr/handler/component/QueryCancellationHandler.java b/solr/core/src/java/org/apache/solr/handler/component/TaskCancellationHandler.java similarity index 68% rename from solr/core/src/java/org/apache/solr/handler/component/QueryCancellationHandler.java rename to solr/core/src/java/org/apache/solr/handler/component/TaskCancellationHandler.java index 18c99ba09c3b..ca6df1b958f1 100644 --- a/solr/core/src/java/org/apache/solr/handler/component/QueryCancellationHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/component/TaskCancellationHandler.java @@ -19,12 +19,10 @@ import static org.apache.solr.common.params.CommonParams.QUERY_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.CancelTaskAPI; +import org.apache.solr.api.JerseyResource; +import org.apache.solr.handler.admin.api.CancelTask; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.request.SolrRequestHandler; import org.apache.solr.response.SolrQueryResponse; @@ -32,40 +30,34 @@ import org.apache.solr.security.PermissionNameProvider; /** Handles requests for query cancellation for cancellable queries */ -public class QueryCancellationHandler extends TaskManagementHandler { +public class TaskCancellationHandler 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 { - ResponseBuilder rb = buildResponseBuilder(req, rsp, getComponentsList()); - Map extraParams = null; + String taskCancellationID = req.getParams().get(QUERY_UUID, null); - rb.setCancellation(true); - - String cancellationUUID = req.getParams().get(QUERY_UUID, null); - - if (cancellationUUID == null) { + if (taskCancellationID == null) { throw new IllegalArgumentException( "Query cancellation was requested but no query UUID for cancellation was given"); } - if (rb.isDistrib) { - extraParams = new HashMap<>(); + boolean isTaskCancelled = ActiveTaskQuerySupport.cancelTask(req, taskCancellationID); - extraParams.put(QUERY_UUID, cancellationUUID); + if (isTaskCancelled) { + rsp.add("status", "Query with queryID " + taskCancellationID + " cancelled successfully"); + rsp.add("responseCode", 200); + } else { + rsp.add("status", "Query with queryID" + taskCancellationID + " not found"); + rsp.add("responseCode", 404); } - // Let this be visible to handleResponses in the handling component - rb.setCancellationUUID(cancellationUUID); - - processRequest(req, rb, extraParams); } @Override public String getDescription() { - return "Cancel queries"; + return "Cancel active tasks"; } @Override @@ -83,7 +75,6 @@ public SolrRequestHandler getSubHandler(String path) { if (path.startsWith("/tasks/cancel")) { return this; } - return null; } @@ -94,14 +85,11 @@ public Boolean registerV2() { @Override public Collection getApis() { - return AnnotatedApi.getApis(new CancelTaskAPI(this)); + return List.of(); } - private List getComponentsList() { - if (components == null) { - components = buildComponentsList(); - } - - return components; + @Override + public Collection> getJerseyResources() { + return List.of(CancelTask.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 3e9c5ec21160..ddc43b79baed 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 @@ -112,9 +112,6 @@ protected void processRequest( public static List buildComponentsList() { List components = new ArrayList<>(2); - QueryCancellationComponent component = new QueryCancellationComponent(); - components.add(component); - return components; } diff --git a/solr/core/src/test/org/apache/solr/core/SolrCoreTest.java b/solr/core/src/test/org/apache/solr/core/SolrCoreTest.java index 9fa63f89801f..19f4f5312e02 100644 --- a/solr/core/src/test/org/apache/solr/core/SolrCoreTest.java +++ b/solr/core/src/test/org/apache/solr/core/SolrCoreTest.java @@ -139,7 +139,7 @@ public void testImplicitPlugins() { ++ihCount; assertEquals(pathToClassMap.get("update"), "solr.V2UpdateRequestHandler"); ++ihCount; - assertEquals(pathToClassMap.get("/tasks/cancel"), "solr.QueryCancellationHandler"); + assertEquals(pathToClassMap.get("/tasks/cancel"), "solr.TaskCancellationHandler"); ++ihCount; assertEquals(pathToClassMap.get("/tasks/list"), "solr.ActiveTasksListHandler"); } From d4721e5d32fc8e2540fd2b1b1eb0a32ba65575b2 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sun, 30 Aug 2026 00:10:56 +0530 Subject: [PATCH 47/70] changes --- .../solr/client/api/endpoint/TasksApi.java | 3 +- .../client/api/model/CancelTaskResponse.java | 19 ++++++++++-- .../solr/handler/admin/api/CancelTask.java | 29 +++++++++++++++++-- .../component/TaskManagementHandler.java | 6 ---- 4 files changed, 45 insertions(+), 12 deletions(-) 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 28fa3b9946ef..d2b9c9216376 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 @@ -24,6 +24,7 @@ import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.ws.rs.PathParam; +import org.apache.solr.client.api.model.CancelTaskResponse; import org.apache.solr.client.api.model.ListActiveTaskResponse; import org.apache.solr.client.api.model.TaskStatusResponse; import org.apache.solr.client.api.util.StoreApiParameters; @@ -57,6 +58,6 @@ interface Cancel { @Operation( summary = "Cancel any specific task", tags = {"tasks"}) - TaskStatusResponse cancelRunningTask(@PathParam("taskID") String taskID) throws Exception; + CancelTaskResponse cancelRunningTask(@PathParam("taskID") String taskID) throws Exception; } } diff --git a/solr/api/src/java/org/apache/solr/client/api/model/CancelTaskResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/CancelTaskResponse.java index 76707a10d86b..62b753e324e4 100644 --- a/solr/api/src/java/org/apache/solr/client/api/model/CancelTaskResponse.java +++ b/solr/api/src/java/org/apache/solr/client/api/model/CancelTaskResponse.java @@ -2,9 +2,24 @@ import com.fasterxml.jackson.annotation.JsonProperty; -public class CancelTaskResponse { +public class CancelTaskResponse extends SolrJerseyResponse { + + public enum CancellationStatus { + SUCCESS("success"), + NOT_FOUND("not_found"); + + private final String value; + + CancellationStatus(String value) { + this.value = value; + } + + public String getValue() { + return this.value; + } + } @JsonProperty - public CancelTaskResponse.TaskStatus status; + public CancelTaskResponse.CancellationStatus status; } diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java b/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java index a1f0e91e94ef..9934d53b3231 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java @@ -1,13 +1,36 @@ 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.client.api.model.CancelTaskResponse; +import org.apache.solr.handler.component.ActiveTaskQuerySupport; +import org.apache.solr.jersey.PermissionName; +import org.apache.solr.request.SolrQueryRequest; public class CancelTask extends JerseyResource implements TasksApi.Cancel { + private final SolrQueryRequest solrQueryRequest; + + @Inject + public CancelTask(SolrQueryRequest solrQueryRequest) { + this.solrQueryRequest = solrQueryRequest; + } + @Override - public TaskStatusResponse cancelRunningTask(String taskID) throws Exception { - return null; + @PermissionName(READ_PERM) + public CancelTaskResponse cancelRunningTask(String taskID) throws Exception { + final CancelTaskResponse response = instantiateJerseyResponse(CancelTaskResponse.class); + + boolean isTaskCancelled = ActiveTaskQuerySupport.cancelTask(solrQueryRequest, taskID); + response.status = + (isTaskCancelled) + ? CancelTaskResponse.CancellationStatus.SUCCESS + : CancelTaskResponse.CancellationStatus.NOT_FOUND; + + return response; } + } 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 ddc43b79baed..a8fa2c9e68f2 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 @@ -109,12 +109,6 @@ protected void processRequest( } } - public static List buildComponentsList() { - List components = new ArrayList<>(2); - - return components; - } - public static ResponseBuilder buildResponseBuilder( SolrQueryRequest req, SolrQueryResponse rsp, List components) { CoreContainer cc = req.getCoreContainer(); From e4e2ac133a8d78344c331171a906e64703747957 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sun, 30 Aug 2026 00:14:32 +0530 Subject: [PATCH 48/70] minimal file --- .../solr/client/api/model/CancelTaskResponse.java | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/solr/api/src/java/org/apache/solr/client/api/model/CancelTaskResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/CancelTaskResponse.java index 62b753e324e4..1705640e7543 100644 --- a/solr/api/src/java/org/apache/solr/client/api/model/CancelTaskResponse.java +++ b/solr/api/src/java/org/apache/solr/client/api/model/CancelTaskResponse.java @@ -5,18 +5,8 @@ public class CancelTaskResponse extends SolrJerseyResponse { public enum CancellationStatus { - SUCCESS("success"), - NOT_FOUND("not_found"); - - private final String value; - - CancellationStatus(String value) { - this.value = value; - } - - public String getValue() { - return this.value; - } + SUCCESS, + NOT_FOUND } @JsonProperty From 20a1f7768e581918e6aa8e6c54956b3416f3238a Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sun, 30 Aug 2026 00:57:27 +0530 Subject: [PATCH 49/70] changes --- .../solr/handler/admin/api/CancelTask.java | 11 +++ .../component/ActiveTaskQuerySupport.java | 75 ++++++++++++------- 2 files changed, 59 insertions(+), 27 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java b/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java index 9934d53b3231..3f0caddf1dc9 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java @@ -9,6 +9,7 @@ import org.apache.solr.handler.component.ActiveTaskQuerySupport; import org.apache.solr.jersey.PermissionName; import org.apache.solr.request.SolrQueryRequest; +import org.apache.solr.search.CancellableCollector; public class CancelTask extends JerseyResource implements TasksApi.Cancel { @@ -25,6 +26,7 @@ public CancelTaskResponse cancelRunningTask(String taskID) throws Exception { final CancelTaskResponse response = instantiateJerseyResponse(CancelTaskResponse.class); boolean isTaskCancelled = ActiveTaskQuerySupport.cancelTask(solrQueryRequest, taskID); + response.status = (isTaskCancelled) ? CancelTaskResponse.CancellationStatus.SUCCESS @@ -33,4 +35,13 @@ public CancelTaskResponse cancelRunningTask(String taskID) throws Exception { return response; } + public static boolean cancelTaskActiveOnThisShard(SolrQueryRequest solrQueryRequest, String taskId) { + CancellableCollector cancellableTask = solrQueryRequest.getCore().getCancellableQueryTracker().getCancellableTask(taskId); + if (cancellableTask != null) { + cancellableTask.cancel(); + return true; + } + return false; + } + } 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 d32daa5f7dd1..f2037b55b956 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 @@ -18,6 +18,7 @@ import static org.apache.solr.common.params.CommonParams.DISTRIB; import static org.apache.solr.common.params.CommonParams.QT; +import static org.apache.solr.common.params.CommonParams.QUERY_UUID; import static org.apache.solr.common.params.CommonParams.TASK_CHECK_UUID; import java.util.ArrayList; @@ -29,53 +30,47 @@ 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.CancelTask; import org.apache.solr.handler.admin.api.ListActiveTasks; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.response.SolrQueryResponse; -import org.apache.solr.search.CancellableCollector; public class ActiveTaskQuerySupport { private static final String ACTIVE_TASK_LIST_HANDLER_PATH = "/tasks/list"; + private static final String CANCEL_TASK_HANDLER_PATH = "/tasks/cancel"; + private ActiveTaskQuerySupport() {} public static List listActiveTasks(SolrQueryRequest req) throws Exception { - return execute(req, null).taskList; + return execute(req, null, false).taskList; } public static boolean isTaskActive(SolrQueryRequest req, String taskId) throws Exception { - return execute(req, taskId).taskActive; + return execute(req, taskId, false).taskActive; } public static boolean cancelTask(SolrQueryRequest req, String taskId) throws Exception { - return cancel(req, taskId); + return execute(req, taskId, true).taskCancelled; } - private static TaskQueryResult execute(SolrQueryRequest req, String taskId) throws Exception { + private static TaskQueryResult execute(SolrQueryRequest req, String taskId, boolean isCancellationRequest) throws Exception { if (!shouldDistributed(req)) { - return localResult(req, taskId); + return localResult(req, taskId, isCancellationRequest); } - return distributedResult(req, taskId); - } - - private static boolean cancel(SolrQueryRequest req, String taskId) { - CancellableCollector cancellableTask = req.getCore().getCancellableQueryTracker().getCancellableTask(taskId); - if (cancellableTask != null) { - cancellableTask.cancel(); - return true; - } - return false; + return distributedResult(req, taskId, isCancellationRequest); } - private static TaskQueryResult localResult(SolrQueryRequest req, String taskId) { + private static TaskQueryResult localResult(SolrQueryRequest req, String taskId, boolean isCancellationRequest) { if (taskId != null) { - return new TaskQueryResult(List.of(), ListActiveTasks.isTaskActiveOnThisShard(req, taskId)); + return (isCancellationRequest) ? + new TaskQueryResult(List.of(), false, CancelTask.cancelTaskActiveOnThisShard(req, taskId)) : + new TaskQueryResult(List.of(), ListActiveTasks.isTaskActiveOnThisShard(req, taskId), false); } - return new TaskQueryResult(ListActiveTasks.getActiveTasksOnThisShard(req), false); + return new TaskQueryResult(ListActiveTasks.getActiveTasksOnThisShard(req), false, false); } - private static TaskQueryResult distributedResult(SolrQueryRequest req, String taskId) - throws Exception { + private static TaskQueryResult distributedResult(SolrQueryRequest req, String taskId, boolean isCancellationRequest) { final ShardHandler shardHandler = req.getCoreContainer().getShardHandlerFactory().getShardHandler(); final ResponseBuilder responseBuilder = @@ -85,7 +80,7 @@ private static TaskQueryResult distributedResult(SolrQueryRequest req, String ta if (!responseBuilder.isDistrib || responseBuilder.shards == null || responseBuilder.shards.length == 0) { - return localResult(req, taskId); + return localResult(req, taskId, isCancellationRequest); } final ShardRequest shardRequest = new ShardRequest(); @@ -95,9 +90,17 @@ private static TaskQueryResult distributedResult(SolrQueryRequest req, String ta for (String shard : shardRequest.actualShards) { ModifiableSolrParams params = new ModifiableSolrParams(); - params.set(QT, ACTIVE_TASK_LIST_HANDLER_PATH); + if (isCancellationRequest) { + params.set(QT, CANCEL_TASK_HANDLER_PATH); + } else { + params.set(QT, ACTIVE_TASK_LIST_HANDLER_PATH); + } if (taskId != null) { - params.set(TASK_CHECK_UUID, taskId); + if (isCancellationRequest) { + params.set(QUERY_UUID, taskId); + } else { + params.set(TASK_CHECK_UUID, taskId); + } } ShardHandler.setShardAttributesToParams(params, shardRequest.purpose); shardHandler.submit(shardRequest, shard, params); @@ -115,9 +118,11 @@ private static TaskQueryResult distributedResult(SolrQueryRequest req, String ta } if (taskId != null) { - return new TaskQueryResult(List.of(), mergeTaskStatus(shardRequest.responses)); + return (isCancellationRequest) ? + new TaskQueryResult(List.of(), false, mergeCancellationStatus(shardRequest.responses)) : + new TaskQueryResult(List.of(), mergeTaskStatus(shardRequest.responses), false); } - return new TaskQueryResult(mergeTaskList(shardRequest.responses), false); + return new TaskQueryResult(mergeTaskList(shardRequest.responses), false, false); } private static boolean shouldDistributed(SolrQueryRequest req) { @@ -142,6 +147,20 @@ private static boolean mergeTaskStatus(List responses) { return false; } + private static boolean mergeCancellationStatus(List responses) { + for (ShardResponse shardResponse : responses) { + Object cancellationStatus = shardResponse.getSolrResponse().getResponse().get("status"); + if (cancellationStatus instanceof Boolean && (Boolean) cancellationStatus) { + return true; + } + + if (cancellationStatus instanceof String && ((String) cancellationStatus).contains("cancelled successfully")) { + return true; + } + } + return false; + } + @SuppressWarnings("unchecked") private static List mergeTaskList(List responses) { Map mergedTasks = new LinkedHashMap<>(); @@ -170,10 +189,12 @@ private static List mergeTaskList(List respons private static final class TaskQueryResult { private final List taskList; private final boolean taskActive; + private final boolean taskCancelled; - private TaskQueryResult(List taskList, boolean taskActive) { + private TaskQueryResult(List taskList, boolean taskActive, boolean taskCancelled) { this.taskList = taskList; this.taskActive = taskActive; + this.taskCancelled = taskCancelled; } } } From b68dd6c369ba9d3f07072dd96fb930beebc50f52 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sun, 30 Aug 2026 01:00:26 +0530 Subject: [PATCH 50/70] added licenses --- .../client/api/model/CancelTaskResponse.java | 17 +++++++++++++++++ .../solr/handler/admin/api/CancelTask.java | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/solr/api/src/java/org/apache/solr/client/api/model/CancelTaskResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/CancelTaskResponse.java index 1705640e7543..448ca0f0bce7 100644 --- a/solr/api/src/java/org/apache/solr/client/api/model/CancelTaskResponse.java +++ b/solr/api/src/java/org/apache/solr/client/api/model/CancelTaskResponse.java @@ -1,3 +1,20 @@ +/* + * 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; diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java b/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java index 3f0caddf1dc9..a2b43fc9b74b 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java @@ -1,3 +1,20 @@ +/* + * 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; From f625a4c440412d57f894a610766d6d88eb8e2f8b Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sun, 30 Aug 2026 01:02:09 +0530 Subject: [PATCH 51/70] tidy up --- .../client/api/model/CancelTaskResponse.java | 4 +-- .../solr/handler/admin/api/CancelTask.java | 9 +++--- .../component/ActiveTaskQuerySupport.java | 30 +++++++++++-------- .../component/TaskCancellationHandler.java | 1 - 4 files changed, 24 insertions(+), 20 deletions(-) diff --git a/solr/api/src/java/org/apache/solr/client/api/model/CancelTaskResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/CancelTaskResponse.java index 448ca0f0bce7..e6d6c507ead8 100644 --- a/solr/api/src/java/org/apache/solr/client/api/model/CancelTaskResponse.java +++ b/solr/api/src/java/org/apache/solr/client/api/model/CancelTaskResponse.java @@ -26,7 +26,5 @@ public enum CancellationStatus { NOT_FOUND } - @JsonProperty - public CancelTaskResponse.CancellationStatus status; - + @JsonProperty public CancelTaskResponse.CancellationStatus status; } diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java b/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java index a2b43fc9b74b..0d62bd13779d 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java @@ -45,20 +45,21 @@ public CancelTaskResponse cancelRunningTask(String taskID) throws Exception { boolean isTaskCancelled = ActiveTaskQuerySupport.cancelTask(solrQueryRequest, taskID); response.status = - (isTaskCancelled) + (isTaskCancelled) ? CancelTaskResponse.CancellationStatus.SUCCESS : CancelTaskResponse.CancellationStatus.NOT_FOUND; return response; } - public static boolean cancelTaskActiveOnThisShard(SolrQueryRequest solrQueryRequest, String taskId) { - CancellableCollector cancellableTask = solrQueryRequest.getCore().getCancellableQueryTracker().getCancellableTask(taskId); + public static boolean cancelTaskActiveOnThisShard( + SolrQueryRequest solrQueryRequest, String taskId) { + CancellableCollector cancellableTask = + solrQueryRequest.getCore().getCancellableQueryTracker().getCancellableTask(taskId); if (cancellableTask != null) { cancellableTask.cancel(); return true; } return false; } - } 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 f2037b55b956..0aa41f1c946b 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 @@ -39,7 +39,6 @@ public class ActiveTaskQuerySupport { private static final String ACTIVE_TASK_LIST_HANDLER_PATH = "/tasks/list"; private static final String CANCEL_TASK_HANDLER_PATH = "/tasks/cancel"; - private ActiveTaskQuerySupport() {} public static List listActiveTasks(SolrQueryRequest req) throws Exception { @@ -54,23 +53,28 @@ public static boolean cancelTask(SolrQueryRequest req, String taskId) throws Exc return execute(req, taskId, true).taskCancelled; } - private static TaskQueryResult execute(SolrQueryRequest req, String taskId, boolean isCancellationRequest) throws Exception { + private static TaskQueryResult execute( + SolrQueryRequest req, String taskId, boolean isCancellationRequest) throws Exception { if (!shouldDistributed(req)) { return localResult(req, taskId, isCancellationRequest); } return distributedResult(req, taskId, isCancellationRequest); } - private static TaskQueryResult localResult(SolrQueryRequest req, String taskId, boolean isCancellationRequest) { + private static TaskQueryResult localResult( + SolrQueryRequest req, String taskId, boolean isCancellationRequest) { if (taskId != null) { - return (isCancellationRequest) ? - new TaskQueryResult(List.of(), false, CancelTask.cancelTaskActiveOnThisShard(req, taskId)) : - new TaskQueryResult(List.of(), ListActiveTasks.isTaskActiveOnThisShard(req, taskId), false); + return (isCancellationRequest) + ? new TaskQueryResult( + List.of(), false, CancelTask.cancelTaskActiveOnThisShard(req, taskId)) + : new TaskQueryResult( + List.of(), ListActiveTasks.isTaskActiveOnThisShard(req, taskId), false); } return new TaskQueryResult(ListActiveTasks.getActiveTasksOnThisShard(req), false, false); } - private static TaskQueryResult distributedResult(SolrQueryRequest req, String taskId, boolean isCancellationRequest) { + private static TaskQueryResult distributedResult( + SolrQueryRequest req, String taskId, boolean isCancellationRequest) { final ShardHandler shardHandler = req.getCoreContainer().getShardHandlerFactory().getShardHandler(); final ResponseBuilder responseBuilder = @@ -118,9 +122,9 @@ private static TaskQueryResult distributedResult(SolrQueryRequest req, String ta } if (taskId != null) { - return (isCancellationRequest) ? - new TaskQueryResult(List.of(), false, mergeCancellationStatus(shardRequest.responses)) : - new TaskQueryResult(List.of(), mergeTaskStatus(shardRequest.responses), false); + return (isCancellationRequest) + ? new TaskQueryResult(List.of(), false, mergeCancellationStatus(shardRequest.responses)) + : new TaskQueryResult(List.of(), mergeTaskStatus(shardRequest.responses), false); } return new TaskQueryResult(mergeTaskList(shardRequest.responses), false, false); } @@ -154,7 +158,8 @@ private static boolean mergeCancellationStatus(List responses) { return true; } - if (cancellationStatus instanceof String && ((String) cancellationStatus).contains("cancelled successfully")) { + if (cancellationStatus instanceof String + && ((String) cancellationStatus).contains("cancelled successfully")) { return true; } } @@ -191,7 +196,8 @@ private static final class TaskQueryResult { private final boolean taskActive; private final boolean taskCancelled; - private TaskQueryResult(List taskList, boolean taskActive, boolean taskCancelled) { + private TaskQueryResult( + List taskList, boolean taskActive, boolean taskCancelled) { this.taskList = taskList; this.taskActive = taskActive; this.taskCancelled = taskCancelled; diff --git a/solr/core/src/java/org/apache/solr/handler/component/TaskCancellationHandler.java b/solr/core/src/java/org/apache/solr/handler/component/TaskCancellationHandler.java index ca6df1b958f1..ebfa79e9e44d 100644 --- a/solr/core/src/java/org/apache/solr/handler/component/TaskCancellationHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/component/TaskCancellationHandler.java @@ -52,7 +52,6 @@ public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throw rsp.add("status", "Query with queryID" + taskCancellationID + " not found"); rsp.add("responseCode", 404); } - } @Override From df41eeea2ba0406fd0bed06f196490a6dde2ccf9 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sun, 30 Aug 2026 01:07:12 +0530 Subject: [PATCH 52/70] response code --- .../org/apache/solr/handler/admin/api/CancelTask.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java b/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java index 0d62bd13779d..47fc92f4ec78 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java @@ -44,10 +44,13 @@ public CancelTaskResponse cancelRunningTask(String taskID) throws Exception { boolean isTaskCancelled = ActiveTaskQuerySupport.cancelTask(solrQueryRequest, taskID); - response.status = - (isTaskCancelled) - ? CancelTaskResponse.CancellationStatus.SUCCESS - : CancelTaskResponse.CancellationStatus.NOT_FOUND; + if (isTaskCancelled) { + response.status = CancelTaskResponse.CancellationStatus.SUCCESS; + response.responseHeader.status = 200; + } else { + response.status = CancelTaskResponse.CancellationStatus.NOT_FOUND; + response.responseHeader.status = 404; + } return response; } From 18de48a9c47ccedf2f9013449b17c3d047b0e09d Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sun, 30 Aug 2026 01:15:49 +0530 Subject: [PATCH 53/70] cleanup --- .../component/TaskManagementHandler.java | 72 ------------------- 1 file changed, 72 deletions(-) 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 a8fa2c9e68f2..ad89247223f1 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 @@ -17,15 +17,8 @@ package org.apache.solr.handler.component; import static org.apache.solr.common.params.CommonParams.DISTRIB; -import static org.apache.solr.common.params.CommonParams.PATH; -import java.io.IOException; -import java.util.ArrayList; import java.util.List; -import java.util.Map; -import org.apache.solr.common.SolrException; -import org.apache.solr.common.params.CommonParams; -import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.core.CoreContainer; import org.apache.solr.core.SolrCore; import org.apache.solr.handler.RequestHandlerBase; @@ -44,71 +37,6 @@ public void inform(SolrCore core) { this.shardHandlerFactory = core.getCoreContainer().getShardHandlerFactory(); } - /** - * Process the actual request. extraParams is required for allowing sub handlers to pass in custom - * parameters to be put in the outgoing shard request - */ - protected void processRequest( - SolrQueryRequest req, ResponseBuilder rb, Map extraParams) - throws IOException { - ShardHandler shardHandler = shardHandlerFactory.getShardHandler(); - List components = rb.components; - - shardHandler.prepDistributed(rb); - - for (SearchComponent c : components) { - c.prepare(rb); - } - - if (!rb.isDistrib) { - for (SearchComponent component : components) { - component.process(rb); - } - } else { - ShardRequest sreq = new ShardRequest(); - - // Distribute to all shards - sreq.shards = rb.shards; - sreq.actualShards = sreq.shards; - - sreq.responses = new ArrayList<>(sreq.actualShards.length); - rb.finished = new ArrayList<>(); - - for (String shard : sreq.actualShards) { - ModifiableSolrParams params = new ModifiableSolrParams(sreq.params); - String reqPath = (String) req.getContext().get(PATH); - - params.set(CommonParams.QT, reqPath); - ShardHandler.setShardAttributesToParams(params, sreq.purpose); - - if (extraParams != null) { - for (Map.Entry entry : extraParams.entrySet()) { - params.set(entry.getKey(), entry.getValue()); - } - } - - shardHandler.submit(sreq, shard, params); - } - - ShardResponse srsp = shardHandler.takeCompletedOrError(); - - if (srsp.getException() != null) { - shardHandler.cancelAll(); - if (srsp.getException() instanceof SolrException) { - throw (SolrException) srsp.getException(); - } else { - throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, srsp.getException()); - } - } - - rb.finished.add(srsp.getShardRequest()); - - for (SearchComponent c : components) { - c.handleResponses(rb, srsp.getShardRequest()); - } - } - } - public static ResponseBuilder buildResponseBuilder( SolrQueryRequest req, SolrQueryResponse rsp, List components) { CoreContainer cc = req.getCoreContainer(); From f6019e6e6202f1a8dfd896d3bd71482c7f3c9cc7 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sun, 30 Aug 2026 11:05:36 +0530 Subject: [PATCH 54/70] fixed tests --- solr/core/src/resources/ImplicitPlugins.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/solr/core/src/resources/ImplicitPlugins.json b/solr/core/src/resources/ImplicitPlugins.json index a9e8dd45ef4c..9929461db937 100644 --- a/solr/core/src/resources/ImplicitPlugins.json +++ b/solr/core/src/resources/ImplicitPlugins.json @@ -144,10 +144,10 @@ } }, "/tasks/cancel": { - "class": "solr.QueryCancellationHandler", + "class": "solr.TaskCancellationHandler", "useParams":"_TASK_CANCELLATION", "components": [ - "querycancellation" + "taskcancellation" ] }, "/tasks/list": { @@ -158,7 +158,7 @@ ] } }, - "queryResponseWriter": { + "queryResponseWriter": { "geojson": { "class": "solr.GeoJSONResponseWriter" }, From 6f1dfac174b2268ea1df335c86374ff9ae55a0d9 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sun, 30 Aug 2026 12:10:30 +0530 Subject: [PATCH 55/70] test fixed --- .../apache/solr/handler/component/TaskCancellationHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solr/core/src/java/org/apache/solr/handler/component/TaskCancellationHandler.java b/solr/core/src/java/org/apache/solr/handler/component/TaskCancellationHandler.java index ebfa79e9e44d..199463cf08a8 100644 --- a/solr/core/src/java/org/apache/solr/handler/component/TaskCancellationHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/component/TaskCancellationHandler.java @@ -49,7 +49,7 @@ public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throw rsp.add("status", "Query with queryID " + taskCancellationID + " cancelled successfully"); rsp.add("responseCode", 200); } else { - rsp.add("status", "Query with queryID" + taskCancellationID + " not found"); + rsp.add("status", "Query with queryID " + taskCancellationID + " not found"); rsp.add("responseCode", 404); } } From f56c06f987888fa284359aadfc43c1a13f6cbd83 Mon Sep 17 00:00:00 2001 From: Eric Pugh Date: Sun, 30 Aug 2026 08:50:20 -0400 Subject: [PATCH 56/70] Add a unit test demonstrating 404 not working --- .../handler/admin/api/CancelTaskTest.java | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 solr/core/src/test/org/apache/solr/handler/admin/api/CancelTaskTest.java diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/CancelTaskTest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/CancelTaskTest.java new file mode 100644 index 000000000000..92ad3a3141d3 --- /dev/null +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/CancelTaskTest.java @@ -0,0 +1,94 @@ +/* + * 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.verify; +import static org.mockito.Mockito.when; + +import org.apache.solr.SolrTestCaseJ4; +import org.apache.solr.client.api.model.CancelTaskResponse; +import org.apache.solr.common.SolrException; +import org.apache.solr.core.CancellableQueryTracker; +import org.apache.solr.core.SolrCore; +import org.apache.solr.request.SolrQueryRequest; +import org.apache.solr.search.CancellableCollector; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +public class CancelTaskTest extends SolrTestCaseJ4 { + + private SolrQueryRequest mockQueryRequest; + private SolrCore solrCore; + private CancellableQueryTracker cancellableQueryTracker; + + private CancelTask cancelTask; + + @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); + + when(mockQueryRequest.getCore()).thenReturn(solrCore); + when(solrCore.getCancellableQueryTracker()).thenReturn(cancellableQueryTracker); + + cancelTask = new CancelTask(mockQueryRequest); + } + + @Test + public void testCancelRunningTask() throws Exception { + CancellableCollector cancellableCollector = mock(CancellableCollector.class); + when(cancellableQueryTracker.getCancellableTask("taskID_running")) + .thenReturn(cancellableCollector); + + CancelTaskResponse response = cancelTask.cancelRunningTask("taskID_running"); + + assertEquals(CancelTaskResponse.CancellationStatus.SUCCESS, response.status); + assertNull(response.error); + verify(cancellableCollector).cancel(); + } + + /** + * Cancelling a task that doesn't exist should produce a real HTTP 404, the same way any other + * v2 API request for a specific resource that isn't found does (see the "Errors" section of + * dev-docs/v2-api-conventions.adoc). That means throwing a {@link SolrException} with {@link + * SolrException.ErrorCode#NOT_FOUND} -- not returning a normal (200) response with a "not + * found" value stuffed inside it, which is what {@code CancelTask.cancelRunningTask} currently + * does. A normal Jersey return always produces a 200 on the wire regardless of what's inside + * the response body; only a thrown exception (via CatchAllExceptionMapper) actually changes the + * HTTP status code. This test intentionally fails against the current implementation. + */ + @Test + public void testCancelNonExistentTaskReturns404() { + when(cancellableQueryTracker.getCancellableTask("taskID_missing")).thenReturn(null); + + SolrException ex = + expectThrows(SolrException.class, () -> cancelTask.cancelRunningTask("taskID_missing")); + assertEquals(SolrException.ErrorCode.NOT_FOUND.code, ex.code()); + } +} From 8f5112a0a5e8fa845a8eaa60f4fbca42282d210d Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sun, 30 Aug 2026 23:22:13 +0530 Subject: [PATCH 57/70] tests fixed --- .../solr/handler/admin/api/CancelTask.java | 9 ++---- .../handler/admin/api/CancelTaskTest.java | 31 +++++-------------- 2 files changed, 11 insertions(+), 29 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java b/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java index 47fc92f4ec78..75629bd7a729 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java @@ -23,6 +23,7 @@ import org.apache.solr.api.JerseyResource; import org.apache.solr.client.api.endpoint.TasksApi; import org.apache.solr.client.api.model.CancelTaskResponse; +import org.apache.solr.common.SolrException; import org.apache.solr.handler.component.ActiveTaskQuerySupport; import org.apache.solr.jersey.PermissionName; import org.apache.solr.request.SolrQueryRequest; @@ -46,13 +47,9 @@ public CancelTaskResponse cancelRunningTask(String taskID) throws Exception { if (isTaskCancelled) { response.status = CancelTaskResponse.CancellationStatus.SUCCESS; - response.responseHeader.status = 200; - } else { - response.status = CancelTaskResponse.CancellationStatus.NOT_FOUND; - response.responseHeader.status = 404; + return response; } - - return response; + throw new SolrException(SolrException.ErrorCode.NOT_FOUND, CancelTaskResponse.CancellationStatus.NOT_FOUND.name()); } public static boolean cancelTaskActiveOnThisShard( diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/CancelTaskTest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/CancelTaskTest.java index 92ad3a3141d3..c9f6a094b996 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/CancelTaskTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/CancelTaskTest.java @@ -34,10 +34,7 @@ public class CancelTaskTest extends SolrTestCaseJ4 { - private SolrQueryRequest mockQueryRequest; - private SolrCore solrCore; private CancellableQueryTracker cancellableQueryTracker; - private CancelTask cancelTask; @BeforeClass @@ -50,45 +47,33 @@ public static void ensureWorkingMockito() { public void setUp() throws Exception { super.setUp(); - mockQueryRequest = mock(SolrQueryRequest.class); - solrCore = mock(SolrCore.class); + SolrQueryRequest solrQueryRequest = mock(SolrQueryRequest.class); + SolrCore solrCore = mock(SolrCore.class); cancellableQueryTracker = mock(CancellableQueryTracker.class); - when(mockQueryRequest.getCore()).thenReturn(solrCore); + when(solrQueryRequest.getCore()).thenReturn(solrCore); when(solrCore.getCancellableQueryTracker()).thenReturn(cancellableQueryTracker); - cancelTask = new CancelTask(mockQueryRequest); + cancelTask = new CancelTask(solrQueryRequest); } @Test public void testCancelRunningTask() throws Exception { CancellableCollector cancellableCollector = mock(CancellableCollector.class); - when(cancellableQueryTracker.getCancellableTask("taskID_running")) - .thenReturn(cancellableCollector); + when(cancellableQueryTracker.getCancellableTask("taskID_running")).thenReturn(cancellableCollector); CancelTaskResponse response = cancelTask.cancelRunningTask("taskID_running"); assertEquals(CancelTaskResponse.CancellationStatus.SUCCESS, response.status); - assertNull(response.error); verify(cancellableCollector).cancel(); } - /** - * Cancelling a task that doesn't exist should produce a real HTTP 404, the same way any other - * v2 API request for a specific resource that isn't found does (see the "Errors" section of - * dev-docs/v2-api-conventions.adoc). That means throwing a {@link SolrException} with {@link - * SolrException.ErrorCode#NOT_FOUND} -- not returning a normal (200) response with a "not - * found" value stuffed inside it, which is what {@code CancelTask.cancelRunningTask} currently - * does. A normal Jersey return always produces a 200 on the wire regardless of what's inside - * the response body; only a thrown exception (via CatchAllExceptionMapper) actually changes the - * HTTP status code. This test intentionally fails against the current implementation. - */ + @Test public void testCancelNonExistentTaskReturns404() { when(cancellableQueryTracker.getCancellableTask("taskID_missing")).thenReturn(null); - SolrException ex = - expectThrows(SolrException.class, () -> cancelTask.cancelRunningTask("taskID_missing")); - assertEquals(SolrException.ErrorCode.NOT_FOUND.code, ex.code()); + SolrException exception = expectThrows(SolrException.class, () -> cancelTask.cancelRunningTask("taskID_missing")); + assertEquals(SolrException.ErrorCode.NOT_FOUND.code, exception.code()); } } From b50d552ab955e9c7531dbed7848ca1b9cce951f8 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sun, 30 Aug 2026 23:23:11 +0530 Subject: [PATCH 58/70] tidying up --- .../java/org/apache/solr/handler/admin/api/CancelTask.java | 3 ++- .../org/apache/solr/handler/admin/api/CancelTaskTest.java | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java b/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java index 75629bd7a729..83c22afa66b3 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java @@ -49,7 +49,8 @@ public CancelTaskResponse cancelRunningTask(String taskID) throws Exception { response.status = CancelTaskResponse.CancellationStatus.SUCCESS; return response; } - throw new SolrException(SolrException.ErrorCode.NOT_FOUND, CancelTaskResponse.CancellationStatus.NOT_FOUND.name()); + throw new SolrException( + SolrException.ErrorCode.NOT_FOUND, CancelTaskResponse.CancellationStatus.NOT_FOUND.name()); } public static boolean cancelTaskActiveOnThisShard( diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/CancelTaskTest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/CancelTaskTest.java index c9f6a094b996..125684a015c4 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/CancelTaskTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/CancelTaskTest.java @@ -60,7 +60,8 @@ public void setUp() throws Exception { @Test public void testCancelRunningTask() throws Exception { CancellableCollector cancellableCollector = mock(CancellableCollector.class); - when(cancellableQueryTracker.getCancellableTask("taskID_running")).thenReturn(cancellableCollector); + when(cancellableQueryTracker.getCancellableTask("taskID_running")) + .thenReturn(cancellableCollector); CancelTaskResponse response = cancelTask.cancelRunningTask("taskID_running"); @@ -68,12 +69,12 @@ public void testCancelRunningTask() throws Exception { verify(cancellableCollector).cancel(); } - @Test public void testCancelNonExistentTaskReturns404() { when(cancellableQueryTracker.getCancellableTask("taskID_missing")).thenReturn(null); - SolrException exception = expectThrows(SolrException.class, () -> cancelTask.cancelRunningTask("taskID_missing")); + SolrException exception = + expectThrows(SolrException.class, () -> cancelTask.cancelRunningTask("taskID_missing")); assertEquals(SolrException.ErrorCode.NOT_FOUND.code, exception.code()); } } From cc6f78886611cc7875735e1ce13292b0d2d16a5f Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sun, 30 Aug 2026 23:25:21 +0530 Subject: [PATCH 59/70] eric as author --- changelog/unreleased/SOLR-18248-cancel-tasks.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog/unreleased/SOLR-18248-cancel-tasks.yml b/changelog/unreleased/SOLR-18248-cancel-tasks.yml index 776891343a0d..d86b6429de1a 100644 --- a/changelog/unreleased/SOLR-18248-cancel-tasks.yml +++ b/changelog/unreleased/SOLR-18248-cancel-tasks.yml @@ -3,6 +3,7 @@ title: type: changed authors: - name: Jalaz Kumar + - name: Eric Pugh links: - name: SOLR-18248 url: https://issues.apache.org/jira/browse/SOLR-18248 From b5dbd12643ec25898cb481edb248d2bbbf756873 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sun, 30 Aug 2026 23:45:30 +0530 Subject: [PATCH 60/70] ref guide --- .../modules/deployment-guide/pages/task-management.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/task-management.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/task-management.adoc index 5cce6eb8bc9c..eb196bbafb40 100644 --- a/solr/solr-ref-guide/modules/deployment-guide/pages/task-management.adoc +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/task-management.adoc @@ -124,7 +124,7 @@ V2 API:: ==== [source,bash] ---- -curl -X GET "http://localhost:8983/v2/collections/collectionName/tasks/cancel?queryUUID=5" +curl -X DELETE "http://localhost:8983/v2/collections/collectionName/tasks/5" ---- ==== ====== From adf337918fc6d0b511c27d60a0fc4b4a81cc4ba2 Mon Sep 17 00:00:00 2001 From: Eric Pugh Date: Mon, 31 Aug 2026 06:31:24 -0400 Subject: [PATCH 61/70] Connect task management to the query params page better. --- .../deployment-guide/pages/task-management.adoc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/task-management.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/task-management.adoc index eb196bbafb40..10481b2b1558 100644 --- a/solr/solr-ref-guide/modules/deployment-guide/pages/task-management.adoc +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/task-management.adoc @@ -23,13 +23,13 @@ Queries are the only type of "task" currently supported, but additional types ma == Registering Tasks for Task Management Task-tracking and management is an opt-in feature: tracking must be explicitly enabled on each individual task. -For queries (the only type of "task" currently supported), this is done by specifying the `canCancel` boolean flag as a query-parameter. -A value of `true` enables task-management; `false` (the default) leaves it disabled. +For queries (the only type of "task" currently supported), this is done by specifying the xref:query-guide:common-query-parameters.adoc#cancancel-parameter[`canCancel`] boolean flag as a query-parameter. +A value of `true` enables task management; `false` (the default) leaves it disabled. -Solr will assign each task a UUID for tracking purposes. -Users may override this if desired with an arbitrary string of their choice using the `queryUUID` query-parameter. +Solr will assign each task an ID for tracking purposes. +Users may override this if desired with an arbitrary string of their choice using the `queryUUID` query-parameter when submitting the original query. (Users are responsible for ensuring that any `queryUUID` values they provide are unique and don't conflict with other running tasks.) -This UUID, whether generated or provided by the user, can then be used to track or cancel the task. +This ID, whether generated or provided by the user, can then be used to track or cancel the task -- as a query parameter with the V1 API, or as part of the URL path with the V2 API; see the sections below for the specifics of each operation. == Task Management Operations Task management interface supports the following types of operations: From 57e8316f4796714f09ab6cbb718b6531e60dcb0a Mon Sep 17 00:00:00 2001 From: Eric Pugh Date: Mon, 31 Aug 2026 06:50:05 -0400 Subject: [PATCH 62/70] simplify the text, and get away from weird "UUID" term everywhere. --- .../pages/task-management.adoc | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/task-management.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/task-management.adoc index 10481b2b1558..e3221924b56d 100644 --- a/solr/solr-ref-guide/modules/deployment-guide/pages/task-management.adoc +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/task-management.adoc @@ -17,22 +17,23 @@ // specific language governing permissions and limitations // under the License. -Solr offers a task management framework, that allows users to monitor (and even cancel) certain types of long-running tasks. +Solr offers a task management framework that allows users to monitor (and even cancel) certain types of long-running tasks. Queries are the only type of "task" currently supported, but additional types may be added in the future. == Registering Tasks for Task Management -Task-tracking and management is an opt-in feature: tracking must be explicitly enabled on each individual task. -For queries (the only type of "task" currently supported), this is done by specifying the xref:query-guide:common-query-parameters.adoc#cancancel-parameter[`canCancel`] boolean flag as a query-parameter. +Task tracking and management is an opt-in feature: tracking must be explicitly enabled on each individual task. +For queries (the only type of "task" currently supported), this is done by specifying the xref:query-guide:common-query-parameters.adoc#cancancel-parameter[`canCancel`] boolean flag as a query parameter. A value of `true` enables task management; `false` (the default) leaves it disabled. Solr will assign each task an ID for tracking purposes. -Users may override this if desired with an arbitrary string of their choice using the `queryUUID` query-parameter when submitting the original query. +Users may override this, if desired, with an arbitrary string of their choice, using the `queryUUID` query parameter when submitting the original query. (Users are responsible for ensuring that any `queryUUID` values they provide are unique and don't conflict with other running tasks.) -This ID, whether generated or provided by the user, can then be used to track or cancel the task -- as a query parameter with the V1 API, or as part of the URL path with the V2 API; see the sections below for the specifics of each operation. +This ID, whether generated or provided by the user, can then be used to track or cancel the task: as a query parameter with the V1 API, or as part of the URL path with the V2 API. +See the sections below for the specifics of each operation. == Task Management Operations -Task management interface supports the following types of operations: +The task management interface supports the following types of operations: . List all currently running cancellable tasks. . Cancel a specific task. @@ -77,7 +78,7 @@ V1 API:: "status":0, "QTime":16}, "taskList":[ - "0,"q=weight_i:[0+TO+200]&canCancel=true&queryUUID=0", + "0","q=weight_i:[0+TO+200]&canCancel=true&queryUUID=0", "5","q=weight_i:[0+TO+200]&canCancel=true&queryUUID=5", "4bcd27bb-0792-4512-a699-532fa7878bd3","q=weight_i:[0+TO+200]&canCancel=true"]} ---- @@ -106,7 +107,7 @@ V2 API:: ==== ====== -== Cancelling An Active Cancellable Task +== Cancelling an Active Cancellable Task To cancel an active task, please use the following syntax: [tabs#cancelalltasks] @@ -130,7 +131,7 @@ curl -X DELETE "http://localhost:8983/v2/collections/collectionName/tasks/5" ====== === Sample Response -==== If the task UUID was found and successfully cancelled: +==== If the task was found and successfully cancelled: ---- { @@ -141,7 +142,7 @@ curl -X DELETE "http://localhost:8983/v2/collections/collectionName/tasks/5" "responseCode":200} ---- -==== If the task UUID was not found +==== If the task was not found: ---- { @@ -177,8 +178,8 @@ curl -X GET "http://localhost:8983/v2/collections/collectionName/tasks/5" ====== === taskUUID Parameter -With the V1 API, the `taskUUID` request parameter is used to specify a task UUID whose status can be checked. -With the V2 API, the task ID is instead supplied as part of the path, e.g. `/v2/collections/collectionName/tasks/{taskID}`. +With the V1 API, the `taskUUID` request parameter specifies which task's status to check. +With the V2 API, the task ID is instead supplied as part of the path, e.g. `/v2/collections/collectionName/tasks/\{taskID}`. === Sample Response From 149e1cfec1db2e06740bcfb0bcb2b5a8af9ddce4 Mon Sep 17 00:00:00 2001 From: Eric Pugh Date: Mon, 31 Aug 2026 06:55:13 -0400 Subject: [PATCH 63/70] components was dead code before, so remove it now. --- solr/core/src/resources/ImplicitPlugins.json | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/solr/core/src/resources/ImplicitPlugins.json b/solr/core/src/resources/ImplicitPlugins.json index 9929461db937..8bb2019695a7 100644 --- a/solr/core/src/resources/ImplicitPlugins.json +++ b/solr/core/src/resources/ImplicitPlugins.json @@ -145,17 +145,11 @@ }, "/tasks/cancel": { "class": "solr.TaskCancellationHandler", - "useParams":"_TASK_CANCELLATION", - "components": [ - "taskcancellation" - ] + "useParams":"_TASK_CANCELLATION" }, "/tasks/list": { "class": "solr.ActiveTasksListHandler", - "useParams":"_LIST_TASKS", - "components": [ - "activetaskslist" - ] + "useParams":"_LIST_TASKS" } }, "queryResponseWriter": { From 22717668bdb45c695bd4a0ce3ebdd689d728fcb9 Mon Sep 17 00:00:00 2001 From: Eric Pugh Date: Mon, 31 Aug 2026 07:18:18 -0400 Subject: [PATCH 64/70] Need seperate documentation for v1 and v2 responses. --- .../pages/task-management.adoc | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/task-management.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/task-management.adoc index e3221924b56d..96033d67c6d8 100644 --- a/solr/solr-ref-guide/modules/deployment-guide/pages/task-management.adoc +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/task-management.adoc @@ -131,8 +131,16 @@ curl -X DELETE "http://localhost:8983/v2/collections/collectionName/tasks/5" ====== === Sample Response + +The V1 and V2 APIs currently return the cancellation result in different shapes. + ==== If the task was found and successfully cancelled: +[tabs#cancelalltasks-response-found] +====== +V1 API:: ++ +==== ---- { "responseHeader":{ @@ -141,9 +149,32 @@ curl -X DELETE "http://localhost:8983/v2/collections/collectionName/tasks/5" "status":"Query with queryID 5 cancelled successfully", "responseCode":200} ---- +==== + +V2 API:: ++ +==== +[source,json] +---- +{ + "responseHeader":{ + "status":0, + "QTime":26}, + "status":"SUCCESS"} +---- +==== +====== ==== If the task was not found: +With the V1 API, a task that isn't found is still a `200` response, with `responseCode` in the body indicating the failure. +With the V2 API, a task that isn't found returns an actual HTTP `404`, with the standard v2 error envelope. + +[tabs#cancelalltasks-response-notfound] +====== +V1 API:: ++ +==== ---- { "responseHeader":{ @@ -152,6 +183,26 @@ curl -X DELETE "http://localhost:8983/v2/collections/collectionName/tasks/5" "status":"Query with queryID 5 not found", "responseCode":404} ---- +==== + +V2 API:: ++ +==== +[source,json] +---- +{ + "responseHeader":{ + "status":404, + "QTime":24}, + "error":{ + "metadata":{ + "error-class":"org.apache.solr.common.SolrException", + "root-error-class":"org.apache.solr.common.SolrException"}, + "code":404, + "msg":"NOT_FOUND"}} +---- +==== +====== == Check Status of a Specific Task To check the status of a specific task, please use the following syntax: From b8520ed5d711ac9f9343386fff34522f28da434e Mon Sep 17 00:00:00 2001 From: Eric Pugh Date: Mon, 31 Aug 2026 07:21:51 -0400 Subject: [PATCH 65/70] Maybe a bit heavy, but since we don't want to change the output format, then we are stuck with this in v1 --- .../solr/handler/component/ActiveTaskQuerySupport.java | 6 ++++++ .../solr/handler/component/TaskCancellationHandler.java | 8 ++++++++ 2 files changed, 14 insertions(+) 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 0aa41f1c946b..fcc52687cf38 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 @@ -151,6 +151,12 @@ private static boolean mergeTaskStatus(List responses) { return false; } + // FRAGILE: relies on substring-matching the human-readable "status" message + // TaskCancellationHandler emits, since that handler has no dedicated machine-readable success + // signal for the shard-to-shard case (unlike mergeTaskStatus() below, whose Boolean branch is + // genuinely reachable via ActiveTasksListHandler's isShardedRequest handling). The `instanceof + // Boolean` branch here is currently unreachable in practice. See the FRAGILE note on + // TaskCancellationHandler.handleRequestBody() before changing that message text. private static boolean mergeCancellationStatus(List responses) { for (ShardResponse shardResponse : responses) { Object cancellationStatus = shardResponse.getSolrResponse().getResponse().get("status"); diff --git a/solr/core/src/java/org/apache/solr/handler/component/TaskCancellationHandler.java b/solr/core/src/java/org/apache/solr/handler/component/TaskCancellationHandler.java index 199463cf08a8..07da307e4588 100644 --- a/solr/core/src/java/org/apache/solr/handler/component/TaskCancellationHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/component/TaskCancellationHandler.java @@ -45,6 +45,14 @@ public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throw boolean isTaskCancelled = ActiveTaskQuerySupport.cancelTask(req, taskCancellationID); + // FRAGILE: these exact "status" message strings are also used as the cross-shard + // cancellation signal -- ActiveTaskQuerySupport.mergeCancellationStatus() matches shard + // sub-responses via `.contains("cancelled successfully")`, since this handler has no + // dedicated machine-readable field for it (unlike ActiveTasksListHandler's isShardedRequest + // handling for task status, which emits a plain boolean for shard-to-shard requests). + // Changing this wording will silently break cross-shard cancellation aggregation; see + // TestTaskManagement.testCrossShardTaskCancellationVisibility, which will start failing if + // that happens. if (isTaskCancelled) { rsp.add("status", "Query with queryID " + taskCancellationID + " cancelled successfully"); rsp.add("responseCode", 200); From a31604f25a708de5e14c980d74e9ff4b87131339 Mon Sep 17 00:00:00 2001 From: Eric Pugh Date: Mon, 31 Aug 2026 09:18:00 -0400 Subject: [PATCH 66/70] adding more tests... --- .../component/ActiveTaskQuerySupport.java | 5 + .../solr/search/TestTaskManagement.java | 111 ++++++++++++++++++ 2 files changed, 116 insertions(+) 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 fcc52687cf38..88198ff25856 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 @@ -157,6 +157,11 @@ private static boolean mergeTaskStatus(List responses) { // genuinely reachable via ActiveTasksListHandler's isShardedRequest handling). The `instanceof // Boolean` branch here is currently unreachable in practice. See the FRAGILE note on // TaskCancellationHandler.handleRequestBody() before changing that message text. + // We didn't want to change the current V1 response output format, so we can't improve this. + // This is used by both V1 and V2 -- CancelTask (V2) calls ActiveTaskQuerySupport.cancelTask(), + // the same entry point TaskCancellationHandler (V1) uses, and distributedResult() always fans + // shard-level sub-requests out over the V1 wire path regardless of which API the original + // request came in on. V2 is not any more robust here. private static boolean mergeCancellationStatus(List responses) { for (ShardResponse shardResponse : responses) { Object cancellationStatus = shardResponse.getSolrResponse().getResponse().get("status"); 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 f1039705765e..724eaf98721a 100644 --- a/solr/core/src/test/org/apache/solr/search/TestTaskManagement.java +++ b/solr/core/src/test/org/apache/solr/search/TestTaskManagement.java @@ -29,7 +29,10 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; +import org.apache.lucene.search.TotalHitCountCollector; import org.apache.lucene.util.BytesRef; +import org.apache.solr.client.api.model.CancelTaskResponse; +import org.apache.solr.client.api.model.IndexType; import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.SolrRequest.SolrRequestType; import org.apache.solr.client.solrj.SolrServerException; @@ -37,6 +40,7 @@ import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.GenericSolrRequest; import org.apache.solr.client.solrj.request.QueryRequest; +import org.apache.solr.client.solrj.request.TasksApi; import org.apache.solr.cloud.SolrCloudTestCase; import org.apache.solr.common.SolrInputDocument; import org.apache.solr.common.cloud.DocCollection; @@ -329,6 +333,113 @@ public void testCrossShardTaskStatusVisibility() throws Exception { } } + /** + * Regression test for cross-shard task cancellation. The current V1 approach is dependent on + * string matching and that makes it brittle, so this helps us make sure no issues creep in. + */ + @Test + public void testCrossShardTaskCancellationVisibility() throws Exception { + DocCollection docCollection = + cluster.getSolrClient().getClusterState().getCollection(COLLECTION_NAME); + List slices = new ArrayList<>(docCollection.getSlices()); + assertEquals("test requires exactly 2 shards", 2, slices.size()); + Replica shard1Leader = slices.get(0).getLeader(); + Replica shard2Leader = slices.get(1).getLeader(); + assumeFalse( + "Both shard leaders landed on the same node — cross-shard scenario cannot be tested", + shard1Leader.getNodeName().equals(shard2Leader.getNodeName())); + + final String taskId = "cross-shard-cancellation-test"; + + JettySolrRunner shard2Jetty = + cluster.getJettySolrRunners().stream() + .filter(j -> j.getNodeName().equals(shard2Leader.getNodeName())) + .findFirst() + .orElseThrow(() -> new AssertionError("No Jetty found for shard 2 leader")); + try (SolrCore shard2Core = shard2Jetty.getCoreContainer().getCore(shard2Leader.getCoreName())) { + assertNotNull("Could not open shard 2 core", shard2Core); + shard2Core + .getCancellableQueryTracker() + .addShardLevelActiveQuery(taskId, new CancellableCollector(new TotalHitCountCollector())); + + try { + try (var shard1Client = + new HttpJettySolrClient.Builder(shard1Leader.getBaseUrl()).build()) { + ModifiableSolrParams params = new ModifiableSolrParams(); + params.set(CommonParams.QUERY_UUID, taskId); + var cancelReq = + new GenericSolrRequest( + SolrRequest.METHOD.POST, "/tasks/cancel", SolrRequestType.ADMIN, params) + .setRequiresCollection(true); + NamedList response = shard1Client.request(cancelReq, COLLECTION_NAME); + + assertEquals( + "Task registered only on shard 2 must be cancellable via cross-shard fan-out from " + + "shard 1. Got: " + + response.get("status"), + 200, + response.get("responseCode")); + } + } finally { + shard2Core.getCancellableQueryTracker().removeCancellableQuery(taskId); + } + } + } + + /** + * Same regression as {@link #testCrossShardTaskCancellationVisibility}, but issued via the V2 API + * instead of the raw V1 request. {@code CancelTask} (V2) calls the same {@code + * ActiveTaskQuerySupport.cancelTask()} entry point V1's {@code TaskCancellationHandler} does, and + * {@code distributedResult()} always fans shard-level sub-requests out over the V1 wire path + * regardless of which API the original request came in on -- so V2 is exposed to the exact same + * string-matching fragility in {@code mergeCancellationStatus()} whenever cross-shard fan-out is + * needed. This test proves that sharing, rather than just asserting it. + */ + @Test + public void testCrossShardTaskCancellationVisibilityV2() throws Exception { + DocCollection docCollection = + cluster.getSolrClient().getClusterState().getCollection(COLLECTION_NAME); + List slices = new ArrayList<>(docCollection.getSlices()); + assertEquals("test requires exactly 2 shards", 2, slices.size()); + Replica shard1Leader = slices.get(0).getLeader(); + Replica shard2Leader = slices.get(1).getLeader(); + assumeFalse( + "Both shard leaders landed on the same node — cross-shard scenario cannot be tested", + shard1Leader.getNodeName().equals(shard2Leader.getNodeName())); + + final String taskId = "cross-shard-cancellation-test-v2"; + + JettySolrRunner shard2Jetty = + cluster.getJettySolrRunners().stream() + .filter(j -> j.getNodeName().equals(shard2Leader.getNodeName())) + .findFirst() + .orElseThrow(() -> new AssertionError("No Jetty found for shard 2 leader")); + try (SolrCore shard2Core = shard2Jetty.getCoreContainer().getCore(shard2Leader.getCoreName())) { + assertNotNull("Could not open shard 2 core", shard2Core); + shard2Core + .getCancellableQueryTracker() + .addShardLevelActiveQuery(taskId, new CancellableCollector(new TotalHitCountCollector())); + + try { + try (var shard1Client = + new HttpJettySolrClient.Builder(shard1Leader.getBaseUrl()).build()) { + var cancelReq = + new TasksApi.CancelRunningTask(IndexType.COLLECTION, COLLECTION_NAME, taskId); + CancelTaskResponse response = cancelReq.process(shard1Client, COLLECTION_NAME); + + assertEquals( + "Task registered only on shard 2 must be cancellable via the V2 API's cross-shard " + + "fan-out from shard 1. Got: " + + response.status, + CancelTaskResponse.CancellationStatus.SUCCESS, + response.status); + } + } finally { + shard2Core.getCancellableQueryTracker().removeCancellableQuery(taskId); + } + } + } + private CompletableFuture cancelQuery( final String queryID, Set cancelledQueryIdsSet, Set notFoundQueryIdSet) { return CompletableFuture.runAsync( From 75ca7308ae89ad613b425ba64a68075a188655d1 Mon Sep 17 00:00:00 2001 From: Eric Pugh Date: Mon, 31 Aug 2026 10:14:45 -0400 Subject: [PATCH 67/70] Javadocs don't need to restart java code paths. Keep them focused. --- .../component/ActiveTaskQuerySupport.java | 15 ++++--------- .../component/TaskCancellationHandler.java | 11 +++------- .../solr/search/TestTaskManagement.java | 22 ++++--------------- 3 files changed, 11 insertions(+), 37 deletions(-) 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 88198ff25856..b6a2fcc8b777 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 @@ -151,17 +151,10 @@ private static boolean mergeTaskStatus(List responses) { return false; } - // FRAGILE: relies on substring-matching the human-readable "status" message - // TaskCancellationHandler emits, since that handler has no dedicated machine-readable success - // signal for the shard-to-shard case (unlike mergeTaskStatus() below, whose Boolean branch is - // genuinely reachable via ActiveTasksListHandler's isShardedRequest handling). The `instanceof - // Boolean` branch here is currently unreachable in practice. See the FRAGILE note on - // TaskCancellationHandler.handleRequestBody() before changing that message text. - // We didn't want to change the current V1 response output format, so we can't improve this. - // This is used by both V1 and V2 -- CancelTask (V2) calls ActiveTaskQuerySupport.cancelTask(), - // the same entry point TaskCancellationHandler (V1) uses, and distributedResult() always fans - // shard-level sub-requests out over the V1 wire path regardless of which API the original - // request came in on. V2 is not any more robust here. + // FRAGILE: matches TaskCancellationHandler's human-readable "status" message by substring, for + // both V1 and V2 (CancelTask calls this same method). Kept as-is since changing the V1 wire + // format is out of scope; see the matching FRAGILE note in + // TaskCancellationHandler.handleRequestBody(). private static boolean mergeCancellationStatus(List responses) { for (ShardResponse shardResponse : responses) { Object cancellationStatus = shardResponse.getSolrResponse().getResponse().get("status"); diff --git a/solr/core/src/java/org/apache/solr/handler/component/TaskCancellationHandler.java b/solr/core/src/java/org/apache/solr/handler/component/TaskCancellationHandler.java index 07da307e4588..a99ba2d1a41e 100644 --- a/solr/core/src/java/org/apache/solr/handler/component/TaskCancellationHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/component/TaskCancellationHandler.java @@ -45,14 +45,9 @@ public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throw boolean isTaskCancelled = ActiveTaskQuerySupport.cancelTask(req, taskCancellationID); - // FRAGILE: these exact "status" message strings are also used as the cross-shard - // cancellation signal -- ActiveTaskQuerySupport.mergeCancellationStatus() matches shard - // sub-responses via `.contains("cancelled successfully")`, since this handler has no - // dedicated machine-readable field for it (unlike ActiveTasksListHandler's isShardedRequest - // handling for task status, which emits a plain boolean for shard-to-shard requests). - // Changing this wording will silently break cross-shard cancellation aggregation; see - // TestTaskManagement.testCrossShardTaskCancellationVisibility, which will start failing if - // that happens. + // FRAGILE: "cancelled successfully" is matched by + // ActiveTaskQuerySupport.mergeCancellationStatus() for cross-shard aggregation. Don't reword + // without checking there and TestTaskManagement.testCrossShardTaskCancellationVisibility*. if (isTaskCancelled) { rsp.add("status", "Query with queryID " + taskCancellationID + " cancelled successfully"); rsp.add("responseCode", 200); 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 724eaf98721a..182ceaa637c0 100644 --- a/solr/core/src/test/org/apache/solr/search/TestTaskManagement.java +++ b/solr/core/src/test/org/apache/solr/search/TestTaskManagement.java @@ -266,17 +266,8 @@ public void testCheckSpecificQueryStatus_Inactive() throws Exception { } /** - * Regression test for cross-shard task visibility. - * - *

On {@code main}, {@code ActiveTasksListHandler.handleRequestBody()} delegates to {@code - * processRequest()}, which fans the request out to every shard via the distributed query - * pipeline. {@code ActiveTasksListComponent.handleResponses()} then aggregates the per-shard - * results, so a task running on shard 2 is visible when the status-check request lands on shard - * 1. - * - *

If this handler is migrated to JAX-RS and the fan-out is replaced with a direct call to the - * handler node's own {@code CancellableQueryTracker}, a task registered only on shard 2 becomes - * invisible to a request handled by shard 1, causing a false "inactive" response. + * Regression test for cross-shard task visibility -- guards against a task on shard 2 becoming + * invisible to a status-check request handled by shard 1. */ @Test public void testCrossShardTaskStatusVisibility() throws Exception { @@ -387,13 +378,8 @@ public void testCrossShardTaskCancellationVisibility() throws Exception { } /** - * Same regression as {@link #testCrossShardTaskCancellationVisibility}, but issued via the V2 API - * instead of the raw V1 request. {@code CancelTask} (V2) calls the same {@code - * ActiveTaskQuerySupport.cancelTask()} entry point V1's {@code TaskCancellationHandler} does, and - * {@code distributedResult()} always fans shard-level sub-requests out over the V1 wire path - * regardless of which API the original request came in on -- so V2 is exposed to the exact same - * string-matching fragility in {@code mergeCancellationStatus()} whenever cross-shard fan-out is - * needed. This test proves that sharing, rather than just asserting it. + * Same as {@link #testCrossShardTaskCancellationVisibility}, but via the V2 API -- confirms V2 + * shares the same cross-shard string-matching fragility as V1. */ @Test public void testCrossShardTaskCancellationVisibilityV2() throws Exception { From 832293fbcfac1055cd9e8590effc3ddec16161d1 Mon Sep 17 00:00:00 2001 From: Eric Pugh Date: Mon, 31 Aug 2026 10:33:30 -0400 Subject: [PATCH 68/70] Reduce our dependency on SolrTestCaseJ4 --- .../handler/admin/api/CancelTaskAPITest.java | 77 +++++++++++++++++++ .../handler/admin/api/CancelTaskTest.java | 5 +- .../handler/admin/api/GetTaskStatusTest.java | 5 +- .../admin/api/ListActiveTasksTest.java | 5 +- 4 files changed, 86 insertions(+), 6 deletions(-) create mode 100644 solr/core/src/test/org/apache/solr/handler/admin/api/CancelTaskAPITest.java diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/CancelTaskAPITest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/CancelTaskAPITest.java new file mode 100644 index 000000000000..38c26d1401a5 --- /dev/null +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/CancelTaskAPITest.java @@ -0,0 +1,77 @@ +/* + * 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.core.CoreContainer.ALLOW_PATHS_SYSPROP; + +import org.apache.lucene.search.TotalHitCountCollector; +import org.apache.solr.SolrTestCase; +import org.apache.solr.client.api.model.CancelTaskResponse; +import org.apache.solr.client.api.model.IndexType; +import org.apache.solr.client.solrj.RemoteSolrException; +import org.apache.solr.client.solrj.request.TasksApi; +import org.apache.solr.core.SolrCore; +import org.apache.solr.search.CancellableCollector; +import org.apache.solr.util.ExternalPaths; +import org.apache.solr.util.SolrJettyTestRule; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; + +/** + * HTTP-level test for the {@link CancelTask} JAX-RS endpoint -- exercises real Jersey route + * registration, DELETE dispatch, response serialization, and HTTP 404 mapping, none of which {@link + * CancelTaskTest} (a direct in-process method call) can catch. + */ +public class CancelTaskAPITest extends SolrTestCase { + + private static final String CORE_NAME = "cancelTaskApiTestCore"; + + @ClassRule public static SolrJettyTestRule solrTestRule = new SolrJettyTestRule(); + + @BeforeClass + public static void beforeClass() throws Exception { + System.setProperty(ALLOW_PATHS_SYSPROP, ExternalPaths.SERVER_HOME.toAbsolutePath().toString()); + solrTestRule.startSolr(createTempDir()); + solrTestRule.newCollection(CORE_NAME).withConfigSet(ExternalPaths.DEFAULT_CONFIGSET).create(); + } + + @Test + public void testCancelRunningTaskHttp() throws Exception { + final String taskId = "cancel-task-api-test"; + try (SolrCore core = solrTestRule.getJetty().getCoreContainer().getCore(CORE_NAME)) { + core.getCancellableQueryTracker() + .addShardLevelActiveQuery(taskId, new CancellableCollector(new TotalHitCountCollector())); + + var req = new TasksApi.CancelRunningTask(IndexType.CORE, CORE_NAME, taskId); + CancelTaskResponse response = req.process(solrTestRule.getSolrClient(null)); + + assertEquals(0, response.responseHeader.status); + assertEquals(CancelTaskResponse.CancellationStatus.SUCCESS, response.status); + } + } + + @Test + public void testCancelNonExistentTaskHttpReturns404() { + var req = new TasksApi.CancelRunningTask(IndexType.CORE, CORE_NAME, "does-not-exist"); + + RemoteSolrException ex = + expectThrows( + RemoteSolrException.class, () -> req.process(solrTestRule.getSolrClient(null))); + assertEquals("Expected 404 for non-existent task", 404, ex.code()); + } +} diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/CancelTaskTest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/CancelTaskTest.java index 125684a015c4..ef1445eeb059 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/CancelTaskTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/CancelTaskTest.java @@ -17,11 +17,12 @@ package org.apache.solr.handler.admin.api; +import static org.apache.solr.SolrTestCaseJ4.assumeWorkingMockito; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import org.apache.solr.SolrTestCaseJ4; +import org.apache.solr.SolrTestCase; import org.apache.solr.client.api.model.CancelTaskResponse; import org.apache.solr.common.SolrException; import org.apache.solr.core.CancellableQueryTracker; @@ -32,7 +33,7 @@ import org.junit.BeforeClass; import org.junit.Test; -public class CancelTaskTest extends SolrTestCaseJ4 { +public class CancelTaskTest extends SolrTestCase { private CancellableQueryTracker cancellableQueryTracker; private CancelTask cancelTask; 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 index acc4fa1d1c7b..0bf04ca29aa5 100644 --- 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 @@ -17,10 +17,11 @@ package org.apache.solr.handler.admin.api; +import static org.apache.solr.SolrTestCaseJ4.assumeWorkingMockito; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import org.apache.solr.SolrTestCaseJ4; +import org.apache.solr.SolrTestCase; import org.apache.solr.client.api.model.TaskStatusResponse; import org.apache.solr.core.CancellableQueryTracker; import org.apache.solr.core.SolrCore; @@ -29,7 +30,7 @@ import org.junit.BeforeClass; import org.junit.Test; -public class GetTaskStatusTest extends SolrTestCaseJ4 { +public class GetTaskStatusTest extends SolrTestCase { private SolrQueryRequest mockQueryRequest; private SolrCore solrCore; 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 index 113f9dcb82a2..28a24977b8cb 100644 --- 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 @@ -17,13 +17,14 @@ package org.apache.solr.handler.admin.api; +import static org.apache.solr.SolrTestCaseJ4.assumeWorkingMockito; 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.SolrTestCase; import org.apache.solr.client.api.model.ListActiveTaskResponse; import org.apache.solr.core.CancellableQueryTracker; import org.apache.solr.core.SolrCore; @@ -32,7 +33,7 @@ import org.junit.BeforeClass; import org.junit.Test; -public class ListActiveTasksTest extends SolrTestCaseJ4 { +public class ListActiveTasksTest extends SolrTestCase { private SolrQueryRequest mockQueryRequest; private SolrCore solrCore; From f56cd9d8c47bfe01088f86e7532ef86b0562d3f6 Mon Sep 17 00:00:00 2001 From: Eric Pugh Date: Mon, 31 Aug 2026 10:35:59 -0400 Subject: [PATCH 69/70] javadocs! --- .../org/apache/solr/client/api/model/CancelTaskResponse.java | 1 + .../src/java/org/apache/solr/handler/admin/api/CancelTask.java | 1 + 2 files changed, 2 insertions(+) diff --git a/solr/api/src/java/org/apache/solr/client/api/model/CancelTaskResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/CancelTaskResponse.java index e6d6c507ead8..41158d6e521f 100644 --- a/solr/api/src/java/org/apache/solr/client/api/model/CancelTaskResponse.java +++ b/solr/api/src/java/org/apache/solr/client/api/model/CancelTaskResponse.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; +/** Response body returned after a task cancellation request. */ public class CancelTaskResponse extends SolrJerseyResponse { public enum CancellationStatus { diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java b/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java index 83c22afa66b3..9cec9fa121b6 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java @@ -29,6 +29,7 @@ import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.search.CancellableCollector; +/** V2 API implementation for cancelling an active task. */ public class CancelTask extends JerseyResource implements TasksApi.Cancel { private final SolrQueryRequest solrQueryRequest; From f2f646dc89bcdcd0339c5ee8dcc7e649745b3b8e Mon Sep 17 00:00:00 2001 From: Eric Pugh Date: Mon, 31 Aug 2026 10:55:04 -0400 Subject: [PATCH 70/70] one more turn of crank --- .../src/java/org/apache/solr/handler/admin/api/CancelTask.java | 3 ++- .../org/apache/solr/handler/admin/api/CancelTaskAPITest.java | 3 +++ .../test/org/apache/solr/handler/admin/api/CancelTaskTest.java | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java b/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java index 9cec9fa121b6..095a981a5566 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/CancelTask.java @@ -50,8 +50,9 @@ public CancelTaskResponse cancelRunningTask(String taskID) throws Exception { response.status = CancelTaskResponse.CancellationStatus.SUCCESS; return response; } + response.status = CancelTaskResponse.CancellationStatus.NOT_FOUND; throw new SolrException( - SolrException.ErrorCode.NOT_FOUND, CancelTaskResponse.CancellationStatus.NOT_FOUND.name()); + SolrException.ErrorCode.NOT_FOUND, "Task with ID '" + taskID + "' not found"); } public static boolean cancelTaskActiveOnThisShard( diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/CancelTaskAPITest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/CancelTaskAPITest.java index 38c26d1401a5..ef85bf2a2121 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/CancelTaskAPITest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/CancelTaskAPITest.java @@ -73,5 +73,8 @@ public void testCancelNonExistentTaskHttpReturns404() { expectThrows( RemoteSolrException.class, () -> req.process(solrTestRule.getSolrClient(null))); assertEquals("Expected 404 for non-existent task", 404, ex.code()); + assertTrue( + "Expected error message to identify the missing task: " + ex.getMessage(), + ex.getMessage().contains("does-not-exist")); } } diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/CancelTaskTest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/CancelTaskTest.java index ef1445eeb059..1fcc1a52083d 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/CancelTaskTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/CancelTaskTest.java @@ -77,5 +77,6 @@ public void testCancelNonExistentTaskReturns404() { SolrException exception = expectThrows(SolrException.class, () -> cancelTask.cancelRunningTask("taskID_missing")); assertEquals(SolrException.ErrorCode.NOT_FOUND.code, exception.code()); + assertTrue(exception.getMessage().contains("taskID_missing")); } }