You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@solr.apache.org by ge...@apache.org on 2023/09/27 17:40:14 UTC
[solr] 02/06: Migrade add-replica to 'api' module
This is an automated email from the ASF dual-hosted git repository.
gerlowskija pushed a commit to branch SOLR-16825-migrate-definitions-to-api-module-pt4
in repository https://gitbox.apache.org/repos/asf/solr.git
commit 0f68b36ab5a4181932db2f942387bf0c871bac60
Author: Jason Gerlowski <ge...@apache.org>
AuthorDate: Tue Sep 26 16:30:15 2023 -0400
Migrade add-replica to 'api' module
---
.../solr/client/api/endpoint/CreateReplicaApi.java | 44 +++++++++
.../client/api/model/CreateReplicaRequestBody.java | 48 ++++++++++
.../solr/handler/admin/CollectionsHandler.java | 9 +-
.../{CreateReplicaAPI.java => CreateReplica.java} | 105 +++++++--------------
.../handler/admin/api/CreateReplicaAPITest.java | 23 ++---
.../solr/jersey/PostRequestLoggingFilterTest.java | 6 +-
6 files changed, 144 insertions(+), 91 deletions(-)
diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/CreateReplicaApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/CreateReplicaApi.java
new file mode 100644
index 00000000000..21c26ea8f49
--- /dev/null
+++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/CreateReplicaApi.java
@@ -0,0 +1,44 @@
+/*
+ * 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 io.swagger.v3.oas.annotations.Operation;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import org.apache.solr.client.api.model.CreateReplicaRequestBody;
+import org.apache.solr.client.api.model.SubResponseAccumulatingJerseyResponse;
+
+/**
+ * V2 API definition for adding a new replica to an existing shard.
+ *
+ * <p>This API (POST /v2/collections/cName/shards/sName/replicas {...}) is analogous to the v1
+ * /admin/collections?action=ADDREPLICA command.
+ */
+@Path("/collections/{collectionName}/shards/{shardName}/replicas")
+public interface CreateReplicaApi {
+
+ @POST
+ @Operation(
+ summary = "Creates a new replica of an existing shard.",
+ tags = {"replicas"})
+ SubResponseAccumulatingJerseyResponse createReplica(
+ @PathParam("collectionName") String collectionName,
+ @PathParam("shardName") String shardName,
+ CreateReplicaRequestBody requestBody)
+ throws Exception;
+}
diff --git a/solr/api/src/java/org/apache/solr/client/api/model/CreateReplicaRequestBody.java b/solr/api/src/java/org/apache/solr/client/api/model/CreateReplicaRequestBody.java
new file mode 100644
index 00000000000..a669cdaf414
--- /dev/null
+++ b/solr/api/src/java/org/apache/solr/client/api/model/CreateReplicaRequestBody.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.client.api.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import java.util.Map;
+
+public class CreateReplicaRequestBody {
+ @JsonProperty public String name;
+ @JsonProperty public String type; // TODO Make this an enum - see SOLR-15796
+ @JsonProperty public String instanceDir;
+ @JsonProperty public String dataDir;
+ @JsonProperty public String ulogDir;
+ @JsonProperty public String route;
+ @JsonProperty public Integer nrtReplicas;
+ @JsonProperty public Integer tlogReplicas;
+ @JsonProperty public Integer pullReplicas;
+ @JsonProperty public Boolean waitForFinalState;
+ @JsonProperty public Boolean followAliases;
+
+ @JsonProperty public String async;
+
+ // TODO This cluster of properties could probably be simplified down to just "nodeSet". See
+ // SOLR-15542
+ @JsonProperty public String node;
+
+ @JsonProperty("nodeSet")
+ public List<String> nodeSet;
+
+ @JsonProperty public Boolean skipNodeAssignment;
+
+ @JsonProperty public Map<String, String> properties;
+}
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 a3ebbf4ae95..5231393ea4e 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
@@ -175,7 +175,7 @@ import org.apache.solr.handler.admin.api.CreateAliasAPI;
import org.apache.solr.handler.admin.api.CreateCollectionAPI;
import org.apache.solr.handler.admin.api.CreateCollectionBackupAPI;
import org.apache.solr.handler.admin.api.CreateCollectionSnapshotAPI;
-import org.apache.solr.handler.admin.api.CreateReplicaAPI;
+import org.apache.solr.handler.admin.api.CreateReplica;
import org.apache.solr.handler.admin.api.CreateShardAPI;
import org.apache.solr.handler.admin.api.DeleteAlias;
import org.apache.solr.handler.admin.api.DeleteCollection;
@@ -942,9 +942,8 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission
final var params = req.getParams();
params.required().check(COLLECTION_PROP, SHARD_ID_PROP);
- final var api = new CreateReplicaAPI(h.coreContainer, req, rsp);
- final var requestBody =
- CreateReplicaAPI.AddReplicaRequestBody.fromV1Params(req.getParams());
+ final var api = new CreateReplica(h.coreContainer, req, rsp);
+ final var requestBody = CreateReplica.createRequestBodyFromV1Params(req.getParams());
final var response =
api.createReplica(
params.get(COLLECTION_PROP), params.get(SHARD_ID_PROP), requestBody);
@@ -1362,7 +1361,7 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission
@Override
public Collection<Class<? extends JerseyResource>> getJerseyResources() {
return List.of(
- CreateReplicaAPI.class,
+ CreateReplica.class,
AddReplicaProperty.class,
BalanceShardUniqueAPI.class,
CreateAliasAPI.class,
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/CreateReplicaAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/CreateReplica.java
similarity index 66%
rename from solr/core/src/java/org/apache/solr/handler/admin/api/CreateReplicaAPI.java
rename to solr/core/src/java/org/apache/solr/handler/admin/api/CreateReplica.java
index c119f27db60..2f34556dbda 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/api/CreateReplicaAPI.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/api/CreateReplica.java
@@ -17,7 +17,6 @@
package org.apache.solr.handler.admin.api;
-import static org.apache.solr.client.solrj.impl.BinaryResponseParser.BINARY_CONTENT_TYPE_V2;
import static org.apache.solr.cloud.Overseer.QUEUE_OPERATION;
import static org.apache.solr.cloud.api.collections.CollectionHandlingUtils.CREATE_NODE_SET;
import static org.apache.solr.common.cloud.ZkStateReader.COLLECTION_PROP;
@@ -41,16 +40,12 @@ import static org.apache.solr.common.params.ShardParams._ROUTE_;
import static org.apache.solr.handler.admin.api.CreateCollectionAPI.copyPrefixedPropertiesWithoutPrefix;
import static org.apache.solr.security.PermissionNameProvider.Name.COLL_EDIT_PERM;
-import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Arrays;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import javax.inject.Inject;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
+import org.apache.solr.client.api.endpoint.CreateReplicaApi;
+import org.apache.solr.client.api.model.CreateReplicaRequestBody;
import org.apache.solr.client.api.model.SubResponseAccumulatingJerseyResponse;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.cloud.ZkNodeProps;
@@ -59,35 +54,29 @@ import org.apache.solr.common.params.CoreAdminParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.CollectionUtil;
import org.apache.solr.core.CoreContainer;
-import org.apache.solr.jersey.JacksonReflectMapWriter;
import org.apache.solr.jersey.PermissionName;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.SolrQueryResponse;
/**
- * V2 API for adding a new replica to an existing shard.
+ * V2 API implementation for adding a new replica to an existing shard.
*
* <p>This API (POST /v2/collections/cName/shards/sName/replicas {...}) is analogous to the v1
* /admin/collections?action=ADDREPLICA command.
*/
-@Path("/collections/{collectionName}/shards/{shardName}/replicas")
-public class CreateReplicaAPI extends AdminAPIBase {
+public class CreateReplica extends AdminAPIBase implements CreateReplicaApi {
@Inject
- public CreateReplicaAPI(
+ public CreateReplica(
CoreContainer coreContainer,
SolrQueryRequest solrQueryRequest,
SolrQueryResponse solrQueryResponse) {
super(coreContainer, solrQueryRequest, solrQueryResponse);
}
- @POST
- @Produces({"application/json", "application/xml", BINARY_CONTENT_TYPE_V2})
@PermissionName(COLL_EDIT_PERM)
public SubResponseAccumulatingJerseyResponse createReplica(
- @PathParam("collectionName") String collectionName,
- @PathParam("shardName") String shardName,
- AddReplicaRequestBody requestBody)
+ String collectionName, String shardName, CreateReplicaRequestBody requestBody)
throws Exception {
final var response = instantiateJerseyResponse(SubResponseAccumulatingJerseyResponse.class);
if (requestBody == null) {
@@ -103,12 +92,12 @@ public class CreateReplicaAPI extends AdminAPIBase {
final ZkNodeProps remoteMessage =
createRemoteMessage(resolvedCollectionName, shardName, requestBody);
submitRemoteMessageAndHandleResponse(
- response, CollectionParams.CollectionAction.ADDREPLICA, remoteMessage, requestBody.asyncId);
+ response, CollectionParams.CollectionAction.ADDREPLICA, remoteMessage, requestBody.async);
return response;
}
public static ZkNodeProps createRemoteMessage(
- String collectionName, String shardName, AddReplicaRequestBody requestBody) {
+ String collectionName, String shardName, CreateReplicaRequestBody requestBody) {
final Map<String, Object> remoteMessage = new HashMap<>();
remoteMessage.put(QUEUE_OPERATION, CollectionParams.CollectionAction.ADDREPLICA.toLower());
remoteMessage.put(COLLECTION_PROP, collectionName);
@@ -129,7 +118,7 @@ public class CreateReplicaAPI extends AdminAPIBase {
insertIfNotNull(remoteMessage, TLOG_REPLICAS, requestBody.tlogReplicas);
insertIfNotNull(remoteMessage, PULL_REPLICAS, requestBody.pullReplicas);
insertIfNotNull(remoteMessage, FOLLOW_ALIASES, requestBody.followAliases);
- insertIfNotNull(remoteMessage, ASYNC, requestBody.asyncId);
+ insertIfNotNull(remoteMessage, ASYNC, requestBody.async);
if (requestBody.properties != null) {
requestBody
@@ -144,59 +133,31 @@ public class CreateReplicaAPI extends AdminAPIBase {
return new ZkNodeProps(remoteMessage);
}
- public static class AddReplicaRequestBody implements JacksonReflectMapWriter {
- @JsonProperty public String name;
- @JsonProperty public String type; // TODO Make this an enum - see SOLR-15796
- @JsonProperty public String instanceDir;
- @JsonProperty public String dataDir;
- @JsonProperty public String ulogDir;
- @JsonProperty public String route;
- @JsonProperty public Integer nrtReplicas;
- @JsonProperty public Integer tlogReplicas;
- @JsonProperty public Integer pullReplicas;
- @JsonProperty public Boolean waitForFinalState;
- @JsonProperty public Boolean followAliases;
-
- @JsonProperty(ASYNC)
- public String asyncId;
-
- // TODO This cluster of properties could probably be simplified down to just "nodeSet". See
- // SOLR-15542
- @JsonProperty public String node;
-
- @JsonProperty("nodeSet")
- public List<String> nodeSet;
-
- @JsonProperty public Boolean skipNodeAssignment;
-
- @JsonProperty public Map<String, String> properties;
-
- public static AddReplicaRequestBody fromV1Params(SolrParams params) {
- final var requestBody = new AddReplicaRequestBody();
-
- requestBody.name = params.get(NAME);
- requestBody.type = params.get(REPLICA_TYPE);
- requestBody.instanceDir = params.get(INSTANCE_DIR);
- requestBody.dataDir = params.get(DATA_DIR);
- requestBody.ulogDir = params.get(ULOG_DIR);
- requestBody.route = params.get(_ROUTE_);
- requestBody.nrtReplicas = params.getInt(NRT_REPLICAS);
- requestBody.tlogReplicas = params.getInt(TLOG_REPLICAS);
- requestBody.pullReplicas = params.getInt(PULL_REPLICAS);
- requestBody.waitForFinalState = params.getBool(WAIT_FOR_FINAL_STATE);
- requestBody.followAliases = params.getBool(FOLLOW_ALIASES);
- requestBody.asyncId = params.get(ASYNC);
-
- requestBody.node = params.get(NODE);
- if (params.get(CREATE_NODE_SET_PARAM) != null) {
- requestBody.nodeSet = Arrays.asList(params.get(CREATE_NODE_SET).split(","));
- }
- requestBody.skipNodeAssignment = params.getBool(SKIP_NODE_ASSIGNMENT);
+ public static CreateReplicaRequestBody createRequestBodyFromV1Params(SolrParams params) {
+ final var requestBody = new CreateReplicaRequestBody();
+
+ requestBody.name = params.get(NAME);
+ requestBody.type = params.get(REPLICA_TYPE);
+ requestBody.instanceDir = params.get(INSTANCE_DIR);
+ requestBody.dataDir = params.get(DATA_DIR);
+ requestBody.ulogDir = params.get(ULOG_DIR);
+ requestBody.route = params.get(_ROUTE_);
+ requestBody.nrtReplicas = params.getInt(NRT_REPLICAS);
+ requestBody.tlogReplicas = params.getInt(TLOG_REPLICAS);
+ requestBody.pullReplicas = params.getInt(PULL_REPLICAS);
+ requestBody.waitForFinalState = params.getBool(WAIT_FOR_FINAL_STATE);
+ requestBody.followAliases = params.getBool(FOLLOW_ALIASES);
+ requestBody.async = params.get(ASYNC);
+
+ requestBody.node = params.get(NODE);
+ if (params.get(CREATE_NODE_SET_PARAM) != null) {
+ requestBody.nodeSet = Arrays.asList(params.get(CREATE_NODE_SET).split(","));
+ }
+ requestBody.skipNodeAssignment = params.getBool(SKIP_NODE_ASSIGNMENT);
- requestBody.properties =
- copyPrefixedPropertiesWithoutPrefix(params, new HashMap<>(), PROPERTY_PREFIX);
+ requestBody.properties =
+ copyPrefixedPropertiesWithoutPrefix(params, new HashMap<>(), PROPERTY_PREFIX);
- return requestBody;
- }
+ return requestBody;
}
}
diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/CreateReplicaAPITest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/CreateReplicaAPITest.java
index d4e9772e866..2abe5d13397 100644
--- a/solr/core/src/test/org/apache/solr/handler/admin/api/CreateReplicaAPITest.java
+++ b/solr/core/src/test/org/apache/solr/handler/admin/api/CreateReplicaAPITest.java
@@ -39,11 +39,12 @@ import static org.apache.solr.common.params.ShardParams._ROUTE_;
import java.util.List;
import java.util.Map;
import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.client.api.model.CreateReplicaRequestBody;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.junit.Test;
-/** Unit tests for {@link CreateReplicaAPI} */
+/** Unit tests for {@link CreateReplica} */
public class CreateReplicaAPITest extends SolrTestCaseJ4 {
@Test
public void testReportsErrorIfRequestBodyMissing() {
@@ -51,7 +52,7 @@ public class CreateReplicaAPITest extends SolrTestCaseJ4 {
expectThrows(
SolrException.class,
() -> {
- final var api = new CreateReplicaAPI(null, null, null);
+ final var api = new CreateReplica(null, null, null);
api.createReplica("someCollName", "someShardName", null);
});
@@ -61,12 +62,12 @@ public class CreateReplicaAPITest extends SolrTestCaseJ4 {
@Test
public void testReportsErrorIfCollectionNameMissing() {
- final var requestBody = new CreateReplicaAPI.AddReplicaRequestBody();
+ final var requestBody = new CreateReplicaRequestBody();
final SolrException thrown =
expectThrows(
SolrException.class,
() -> {
- final var api = new CreateReplicaAPI(null, null, null);
+ final var api = new CreateReplica(null, null, null);
api.createReplica(null, "shardName", requestBody);
});
@@ -76,12 +77,12 @@ public class CreateReplicaAPITest extends SolrTestCaseJ4 {
@Test
public void testReportsErrorIfShardNameMissing() {
- final var requestBody = new CreateReplicaAPI.AddReplicaRequestBody();
+ final var requestBody = new CreateReplicaRequestBody();
final SolrException thrown =
expectThrows(
SolrException.class,
() -> {
- final var api = new CreateReplicaAPI(null, null, null);
+ final var api = new CreateReplica(null, null, null);
api.createReplica("someCollectionName", null, requestBody);
});
@@ -91,7 +92,7 @@ public class CreateReplicaAPITest extends SolrTestCaseJ4 {
@Test
public void testCreateRemoteMessageAllProperties() {
- final var requestBody = new CreateReplicaAPI.AddReplicaRequestBody();
+ final var requestBody = new CreateReplicaRequestBody();
requestBody.name = "someName";
requestBody.type = "NRT";
requestBody.instanceDir = "/some/dir1";
@@ -106,11 +107,11 @@ public class CreateReplicaAPITest extends SolrTestCaseJ4 {
requestBody.skipNodeAssignment = Boolean.TRUE;
requestBody.waitForFinalState = true;
requestBody.followAliases = true;
- requestBody.asyncId = "someAsyncId";
+ requestBody.async = "someAsyncId";
requestBody.properties = Map.of("propName1", "propVal1", "propName2", "propVal2");
final var remoteMessage =
- CreateReplicaAPI.createRemoteMessage("someCollectionName", "someShardName", requestBody)
+ CreateReplica.createRemoteMessage("someCollectionName", "someShardName", requestBody)
.getProperties();
assertEquals(20, remoteMessage.size());
@@ -159,7 +160,7 @@ public class CreateReplicaAPITest extends SolrTestCaseJ4 {
v1Params.add("property.propName1", "propVal1");
v1Params.add("property.propName2", "propVal2");
- final var requestBody = CreateReplicaAPI.AddReplicaRequestBody.fromV1Params(v1Params);
+ final var requestBody = CreateReplica.createRequestBodyFromV1Params(v1Params);
assertEquals("someName", requestBody.name);
assertEquals("NRT", requestBody.type);
@@ -175,7 +176,7 @@ public class CreateReplicaAPITest extends SolrTestCaseJ4 {
assertEquals(Boolean.TRUE, requestBody.skipNodeAssignment);
assertEquals(Boolean.TRUE, requestBody.waitForFinalState);
assertEquals(Boolean.TRUE, requestBody.followAliases);
- assertEquals("someAsyncId", requestBody.asyncId);
+ assertEquals("someAsyncId", requestBody.async);
assertEquals("propVal1", requestBody.properties.get("propName1"));
assertEquals("propVal2", requestBody.properties.get("propName2"));
}
diff --git a/solr/core/src/test/org/apache/solr/jersey/PostRequestLoggingFilterTest.java b/solr/core/src/test/org/apache/solr/jersey/PostRequestLoggingFilterTest.java
index c0770c4912e..985085b7829 100644
--- a/solr/core/src/test/org/apache/solr/jersey/PostRequestLoggingFilterTest.java
+++ b/solr/core/src/test/org/apache/solr/jersey/PostRequestLoggingFilterTest.java
@@ -26,7 +26,7 @@ import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.UriInfo;
import org.apache.solr.SolrTestCaseJ4;
-import org.apache.solr.handler.admin.api.CreateReplicaAPI;
+import org.apache.solr.client.api.model.CreateReplicaRequestBody;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -122,10 +122,10 @@ public class PostRequestLoggingFilterTest extends SolrTestCaseJ4 {
@Test
public void testRequestBodyRepresentedAsJsonWhenFound() {
- final var requestBody = new CreateReplicaAPI.AddReplicaRequestBody();
+ final var requestBody = new CreateReplicaRequestBody();
requestBody.name = "someReplicaName";
requestBody.type = "NRT";
- requestBody.asyncId = "someAsyncId";
+ requestBody.async = "someAsyncId";
final var mockContext = mock(ContainerRequestContext.class);
when(mockContext.getProperty(DESERIALIZED_REQUEST_BODY_KEY)).thenReturn(requestBody);