Skip to content

Commit

Permalink
Migrate balance-shard-unique API
Browse files Browse the repository at this point in the history
  • Loading branch information
gerlowskija committed Dec 4, 2023
1 parent 8f00dd2 commit a5138fc
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 48 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* 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.BalanceShardUniqueRequestBody;
import org.apache.solr.client.api.model.SubResponseAccumulatingJerseyResponse;

/**
* V2 API definition for insuring that a specified per-shard property is distributed evenly amongst
* the physical nodes comprising a collection.
*
* <p>The new API (POST /v2/collections/collectionName/balance-shard-unique {...} ) is analogous to
* the v1 /admin/collections?action=BALANCESHARDUNIQUE command.
*/
@Path("/collections/{collectionName}/balance-shard-unique")
public interface BalanceShardUniqueApi {
@POST
@Operation(
summary =
"Ensure a specified per-shard property is distributed evenly amongst physical nodes comprising a collection",
tags = {"collections"})
SubResponseAccumulatingJerseyResponse balanceShardUnique(
@PathParam("collectionName") String collectionName, BalanceShardUniqueRequestBody requestBody)
throws Exception;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.solr.client.api.model;

import com.fasterxml.jackson.annotation.JsonProperty;

public class BalanceShardUniqueRequestBody {
@JsonProperty(required = true)
public String property;

public Boolean onlyActiveNodes;

public Boolean shardUnique;

public String async;
}
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@
import org.apache.solr.handler.admin.api.AdminAPIBase;
import org.apache.solr.handler.admin.api.AliasProperty;
import org.apache.solr.handler.admin.api.BalanceReplicas;
import org.apache.solr.handler.admin.api.BalanceShardUniqueAPI;
import org.apache.solr.handler.admin.api.BalanceShardUnique;
import org.apache.solr.handler.admin.api.CollectionProperty;
import org.apache.solr.handler.admin.api.CollectionStatusAPI;
import org.apache.solr.handler.admin.api.CreateAliasAPI;
Expand Down Expand Up @@ -1024,7 +1024,7 @@ public Map<String, Object> execute(
BALANCESHARDUNIQUE_OP(
BALANCESHARDUNIQUE,
(req, rsp, h) -> {
BalanceShardUniqueAPI.invokeFromV1Params(h.coreContainer, req, rsp);
BalanceShardUnique.invokeFromV1Params(h.coreContainer, req, rsp);
return null;
}),
REBALANCELEADERS_OP(
Expand Down Expand Up @@ -1363,7 +1363,7 @@ public Collection<Class<? extends JerseyResource>> getJerseyResources() {
return List.of(
CreateReplica.class,
AddReplicaProperty.class,
BalanceShardUniqueAPI.class,
BalanceShardUnique.class,
CreateAliasAPI.class,
CreateCollection.class,
CreateCollectionBackup.class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,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.ONLY_ACTIVE_NODES;
import static org.apache.solr.cloud.api.collections.CollectionHandlingUtils.SHARD_UNIQUE;
Expand All @@ -30,47 +29,37 @@
import java.util.Locale;
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.BalanceShardUniqueApi;
import org.apache.solr.client.api.model.BalanceShardUniqueRequestBody;
import org.apache.solr.client.api.model.SubResponseAccumulatingJerseyResponse;
import org.apache.solr.cloud.overseer.SliceMutator;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.annotation.JsonProperty;
import org.apache.solr.common.cloud.ZkNodeProps;
import org.apache.solr.common.params.CollectionParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.core.CoreContainer;
import org.apache.solr.handler.api.V2ApiUtils;
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 insuring that a particular property is distributed evenly amongst the physical nodes
* comprising a collection.
*
* <p>The new API (POST /v2/collections/collectionName/balance-shard-unique {...} ) is analogous to
* the v1 /admin/collections?action=BALANCESHARDUNIQUE command.
* V2 API implementation for insuring that a particular property is distributed evenly amongst the
* physical nodes comprising a collection.
*/
@Path("/collections/{collectionName}/balance-shard-unique")
public class BalanceShardUniqueAPI extends AdminAPIBase {
public class BalanceShardUnique extends AdminAPIBase implements BalanceShardUniqueApi {
@Inject
public BalanceShardUniqueAPI(
public BalanceShardUnique(
CoreContainer coreContainer,
SolrQueryRequest solrQueryRequest,
SolrQueryResponse solrQueryResponse) {
super(coreContainer, solrQueryRequest, solrQueryResponse);
}

@POST
@Produces({"application/json", "application/xml", BINARY_CONTENT_TYPE_V2})
@Override
@PermissionName(COLL_EDIT_PERM)
public SubResponseAccumulatingJerseyResponse balanceShardUnique(
@PathParam("collectionName") String collectionName, BalanceShardUniqueRequestBody requestBody)
throws Exception {
String collectionName, BalanceShardUniqueRequestBody requestBody) throws Exception {
final var response = instantiateJerseyResponse(SubResponseAccumulatingJerseyResponse.class);
if (requestBody == null) {
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Missing required request body");
Expand All @@ -86,7 +75,7 @@ public SubResponseAccumulatingJerseyResponse balanceShardUnique(
response,
CollectionParams.CollectionAction.BALANCESHARDUNIQUE,
remoteMessage,
requestBody.asyncId);
requestBody.async);

return response;
}
Expand All @@ -100,7 +89,7 @@ public static ZkNodeProps createRemoteMessage(
remoteMessage.put(PROPERTY_PROP, requestBody.property);
insertIfNotNull(remoteMessage, ONLY_ACTIVE_NODES, requestBody.onlyActiveNodes);
insertIfNotNull(remoteMessage, SHARD_UNIQUE, requestBody.shardUnique);
insertIfNotNull(remoteMessage, ASYNC, requestBody.asyncId);
insertIfNotNull(remoteMessage, ASYNC, requestBody.async);

return new ZkNodeProps(remoteMessage);
}
Expand All @@ -110,7 +99,7 @@ public static void invokeFromV1Params(
SolrQueryRequest solrQueryRequest,
SolrQueryResponse solrQueryResponse)
throws Exception {
final var api = new BalanceShardUniqueAPI(coreContainer, solrQueryRequest, solrQueryResponse);
final var api = new BalanceShardUnique(coreContainer, solrQueryRequest, solrQueryResponse);
final SolrParams params = solrQueryRequest.getParams();
params.required().check(COLLECTION_PROP, PROPERTY_PROP);

Expand All @@ -119,25 +108,12 @@ public static void invokeFromV1Params(
requestBody.property = params.get(PROPERTY_PROP);
requestBody.onlyActiveNodes = params.getBool(ONLY_ACTIVE_NODES);
requestBody.shardUnique = params.getBool(SHARD_UNIQUE);
requestBody.asyncId = params.get(ASYNC);
requestBody.async = params.get(ASYNC);

V2ApiUtils.squashIntoSolrResponseWithoutHeader(
solrQueryResponse, api.balanceShardUnique(collection, requestBody));
}

public static class BalanceShardUniqueRequestBody implements JacksonReflectMapWriter {
@JsonProperty(required = true)
public String property;

@JsonProperty(ONLY_ACTIVE_NODES)
public Boolean onlyActiveNodes;

@JsonProperty public Boolean shardUnique;

@JsonProperty(ASYNC)
public String asyncId;
}

private void validatePropertyToBalance(String prop, boolean shardUnique) {
prop = prop.toLowerCase(Locale.ROOT);
if (!prop.startsWith(PROPERTY_PREFIX)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@
import static org.apache.solr.common.params.CommonAdminParams.ASYNC;

import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.client.api.model.BalanceShardUniqueRequestBody;
import org.apache.solr.common.SolrException;
import org.junit.Test;

/** Unit tests for {@link BalanceShardUniqueAPI} */
/** Unit tests for {@link BalanceShardUnique} */
public class BalanceShardUniqueAPITest extends SolrTestCaseJ4 {

@Test
Expand All @@ -37,7 +38,7 @@ public void testReportsErrorIfRequestBodyMissing() {
expectThrows(
SolrException.class,
() -> {
final var api = new BalanceShardUniqueAPI(null, null, null);
final var api = new BalanceShardUnique(null, null, null);
api.balanceShardUnique("someCollectionName", null);
});

Expand All @@ -47,13 +48,13 @@ public void testReportsErrorIfRequestBodyMissing() {

@Test
public void testReportsErrorIfCollectionNameMissing() {
final var requestBody = new BalanceShardUniqueAPI.BalanceShardUniqueRequestBody();
final var requestBody = new BalanceShardUniqueRequestBody();
requestBody.property = "preferredLeader";
final SolrException thrown =
expectThrows(
SolrException.class,
() -> {
final var api = new BalanceShardUniqueAPI(null, null, null);
final var api = new BalanceShardUnique(null, null, null);
api.balanceShardUnique(null, requestBody);
});

Expand All @@ -64,12 +65,12 @@ public void testReportsErrorIfCollectionNameMissing() {
@Test
public void testReportsErrorIfPropertyToBalanceIsMissing() {
// Note, 'property' param on reqBody not set
final var requestBody = new BalanceShardUniqueAPI.BalanceShardUniqueRequestBody();
final var requestBody = new BalanceShardUniqueRequestBody();
final SolrException thrown =
expectThrows(
SolrException.class,
() -> {
final var api = new BalanceShardUniqueAPI(null, null, null);
final var api = new BalanceShardUnique(null, null, null);
api.balanceShardUnique("someCollName", requestBody);
});

Expand All @@ -79,13 +80,13 @@ public void testReportsErrorIfPropertyToBalanceIsMissing() {

@Test
public void testCreateRemoteMessageAllProperties() {
final var requestBody = new BalanceShardUniqueAPI.BalanceShardUniqueRequestBody();
final var requestBody = new BalanceShardUniqueRequestBody();
requestBody.property = "someProperty";
requestBody.shardUnique = Boolean.TRUE;
requestBody.onlyActiveNodes = Boolean.TRUE;
requestBody.asyncId = "someAsyncId";
requestBody.async = "someAsyncId";
final var remoteMessage =
BalanceShardUniqueAPI.createRemoteMessage("someCollName", requestBody).getProperties();
BalanceShardUnique.createRemoteMessage("someCollName", requestBody).getProperties();

assertEquals(6, remoteMessage.size());
assertEquals("balanceshardunique", remoteMessage.get(QUEUE_OPERATION));
Expand Down

0 comments on commit a5138fc

Please sign in to comment.