This is an automated email from the ASF dual-hosted git repository.
epugh pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr.git
The following commit(s) were added to refs/heads/main by this push:
new 597ed677408 SOLR-16396 | Migrate GET /config/overlay and GET
/config/znodeVersion to JAX-RS. (#5022)
597ed677408 is described below
commit 597ed67740831566b708b793f52554b2e49e7e17
Author: Jalaz Kumar <[email protected]>
AuthorDate: Mon Oct 12 17:46:01 2026 +0530
SOLR-16396 | Migrate GET /config/overlay and GET /config/znodeVersion to
JAX-RS. (#5022)
---
.../unreleased/SOLR-16396-config-get-others.yml | 9 ++
.../apache/solr/client/api/endpoint/ConfigApi.java | 26 +++++
.../client/api/model/ConfigOverlayResponse.java | 25 +++++
.../api/model/ConfigZnodeVersionResponse.java | 32 ++++++
.../org/apache/solr/handler/SolrConfigHandler.java | 122 ++++++++++-----------
.../apache/solr/handler/admin/api/GetConfig.java | 29 +++++
.../solr/handler/admin/api/GetConfigAPI.java | 2 -
.../solr/handler/admin/V2ConfigAPIMappingTest.java | 2 -
.../handler/admin/api/GetConfigSolrCloudTest.java | 26 ++++-
.../solr/handler/admin/api/GetConfigTest.java | 24 ++++
.../solrj/src/resources/java-template/api.mustache | 8 +-
11 files changed, 234 insertions(+), 71 deletions(-)
diff --git a/changelog/unreleased/SOLR-16396-config-get-others.yml
b/changelog/unreleased/SOLR-16396-config-get-others.yml
new file mode 100644
index 00000000000..56e36c32586
--- /dev/null
+++ b/changelog/unreleased/SOLR-16396-config-get-others.yml
@@ -0,0 +1,9 @@
+title:
+ Migrate GET /config/overlay and GET /config/znodeVersion to JAX-RS.
+type: changed
+authors:
+ - name: Jalaz Kumar
+ nick: jaykay12
+links:
+ - name: SOLR-16396
+ url: https://issues.apache.org/jira/browse/SOLR-16396
diff --git
a/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java
b/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java
index 3e0ab463af2..cc9cecc1bb5 100644
--- a/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java
+++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java
@@ -25,6 +25,8 @@ import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.QueryParam;
import org.apache.solr.client.api.model.ConfigInfoResponse;
+import org.apache.solr.client.api.model.ConfigOverlayResponse;
+import org.apache.solr.client.api.model.ConfigZnodeVersionResponse;
import org.apache.solr.client.api.util.StoreApiParameters;
/** V2 API for reading and modifying a core/collection's config */
@@ -42,5 +44,29 @@ public interface ConfigApi {
@DefaultValue("false")
@Parameter(description = "Expand request handler useParams and
effective parameters")
boolean expandParams);
+
+ @GET
+ @Path("/overlay")
+ @StoreApiParameters
+ @Operation(
+ summary = "Fetch the config overlay of the specified core or
collection",
+ tags = {"config"})
+ ConfigOverlayResponse getOverlay();
+
+ @GET
+ @Path("/znodeVersion")
+ @StoreApiParameters
+ @Operation(
+ summary = "Fetch znode versions for config overlay and request params",
+ tags = {"config"})
+ ConfigZnodeVersionResponse getZnodeVersion(
+ @QueryParam("overlay")
+ @DefaultValue("-1")
+ @Parameter(description = "Expected overlay znode version")
+ int expectedOverlayVersion,
+ @QueryParam("params")
+ @DefaultValue("-1")
+ @Parameter(description = "Expected request-params znode version")
+ int expectedParamsVersion);
}
}
diff --git
a/solr/api/src/java/org/apache/solr/client/api/model/ConfigOverlayResponse.java
b/solr/api/src/java/org/apache/solr/client/api/model/ConfigOverlayResponse.java
new file mode 100644
index 00000000000..e75aaf25fba
--- /dev/null
+++
b/solr/api/src/java/org/apache/solr/client/api/model/ConfigOverlayResponse.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.client.api.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Map;
+
+public class ConfigOverlayResponse extends SolrJerseyResponse {
+ @JsonProperty("overlay")
+ public Map<String, Object> overlay;
+}
diff --git
a/solr/api/src/java/org/apache/solr/client/api/model/ConfigZnodeVersionResponse.java
b/solr/api/src/java/org/apache/solr/client/api/model/ConfigZnodeVersionResponse.java
new file mode 100644
index 00000000000..01cecfaa73f
--- /dev/null
+++
b/solr/api/src/java/org/apache/solr/client/api/model/ConfigZnodeVersionResponse.java
@@ -0,0 +1,32 @@
+/*
+ * 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 ConfigZnodeVersionResponse extends SolrJerseyResponse {
+ @JsonProperty("znodeVersion")
+ public ZnodeVersions znodeVersion;
+
+ public static class ZnodeVersions {
+ @JsonProperty("overlay")
+ public int overlay;
+
+ @JsonProperty("params")
+ public int params;
+ }
+}
diff --git a/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java
b/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java
index d943272657f..d61b7d2bacb 100644
--- a/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java
@@ -174,7 +174,7 @@ public class SolrConfigHandler extends RequestHandlerBase
return immutable != null && Boolean.parseBoolean(immutable.toString());
}
- private class Command {
+ private static class Command {
private final SolrQueryRequest req;
private final SolrQueryResponse resp;
private final String method;
@@ -202,7 +202,7 @@ public class SolrConfigHandler extends RequestHandlerBase
resp, new
GetConfig(req).getConfig(req.getParams().getBool("expandParams", false)));
} else {
if (ConfigOverlay.NAME.equals(parts.get(1))) {
- resp.add(ConfigOverlay.NAME,
req.getCore().getSolrConfig().getOverlay());
+ V2ApiUtils.squashIntoSolrResponseWithoutHeader(resp, new
GetConfig(req).getOverlay());
} else if (RequestParams.NAME.equals(parts.get(1))) {
if (parts.size() == 3) {
RequestParams params =
req.getCore().getSolrConfig().getRequestParams();
@@ -219,66 +219,12 @@ public class SolrConfigHandler extends RequestHandlerBase
} else {
if (ZNODEVER.equals(parts.get(1))) {
- resp.add(
- ZNODEVER,
- Map.of(
- ConfigOverlay.NAME,
- req.getCore().getSolrConfig().getOverlay().getVersion(),
- RequestParams.NAME,
-
req.getCore().getSolrConfig().getRequestParams().getZnodeVersion()));
- boolean isStale = false;
- int expectedVersion = req.getParams().getInt(ConfigOverlay.NAME,
-1);
- int actualVersion =
req.getCore().getSolrConfig().getOverlay().getVersion();
- if (expectedVersion > actualVersion) {
- log.info(
- "expecting overlay version {} but my version is {}",
- expectedVersion,
- actualVersion);
- isStale = true;
- } else if (expectedVersion != -1) {
- log.info("I already have the expected version {} of config",
expectedVersion);
- }
- expectedVersion = req.getParams().getInt(RequestParams.NAME, -1);
- actualVersion =
req.getCore().getSolrConfig().getRequestParams().getZnodeVersion();
- if (expectedVersion > actualVersion) {
- log.info(
- "expecting params version {} but my version is {}",
- expectedVersion,
- actualVersion);
- isStale = true;
- } else if (expectedVersion != -1) {
- log.info("I already have the expected version {} of params",
expectedVersion);
- }
- if (isStale && req.getCore().getResourceLoader() instanceof
ZkSolrResourceLoader) {
- new Thread(
- () -> {
- if (!reloadLock.tryLock()) {
- log.info("Another reload is in progress . Not doing
anything");
- return;
- }
- try {
- log.info("Trying to update my configs");
- SolrCore.getConfListener(
- req.getCore(),
- (ZkSolrResourceLoader)
req.getCore().getResourceLoader())
- .run();
- } catch (Exception e) {
- log.error("Unable to refresh conf ", e);
- } finally {
- reloadLock.unlock();
- }
- },
- SolrConfigHandler.class.getSimpleName() + "-refreshconf")
- .start();
- } else {
- if (log.isInfoEnabled()) {
- log.info(
- "isStale {} , resourceloader {}",
- isStale,
- req.getCore().getResourceLoader().getClass().getName());
- }
- }
-
+ V2ApiUtils.squashIntoSolrResponseWithoutHeader(
+ resp,
+ new GetConfig(req)
+ .getZnodeVersion(
+ req.getParams().getInt(ConfigOverlay.NAME, -1),
+ req.getParams().getInt(RequestParams.NAME, -1)));
} else {
Map<String, Object> m = getConfigDetails(parts.get(1), req);
Map<String, Object> val = new LinkedHashMap<>();
@@ -970,6 +916,58 @@ public class SolrConfigHandler extends RequestHandlerBase
return activeReplicas;
}
+ public static void maybeRefreshStaleConfig(
+ SolrCore core, int expectedOverlayVersion, int expectedParamsVersion) {
+ boolean isStale =
+ isExpectedVersionStale(
+ "overlay", expectedOverlayVersion,
core.getSolrConfig().getOverlay().getVersion())
+ | isExpectedVersionStale(
+ "params",
+ expectedParamsVersion,
+ core.getSolrConfig().getRequestParams().getZnodeVersion());
+ if (isStale && core.getResourceLoader() instanceof ZkSolrResourceLoader) {
+ final Lock reloadLock =
+ ((SolrConfigHandler)
core.getRequestHandler("/config")).getReloadLock();
+ new Thread(
+ () -> {
+ if (!reloadLock.tryLock()) {
+ log.info("Another reload is in progress . Not doing
anything");
+ return;
+ }
+ try {
+ log.info("Trying to update my configs");
+ SolrCore.getConfListener(core, (ZkSolrResourceLoader)
core.getResourceLoader())
+ .run();
+ } catch (Exception e) {
+ log.error("Unable to refresh conf ", e);
+ } finally {
+ reloadLock.unlock();
+ }
+ },
+ SolrConfigHandler.class.getSimpleName() + "-refreshconf")
+ .start();
+ } else {
+ if (log.isInfoEnabled()) {
+ log.info(
+ "isStale {} , resourceloader {}",
+ isStale,
+ core.getResourceLoader().getClass().getName());
+ }
+ }
+ }
+
+ private static boolean isExpectedVersionStale(String label, int expected,
int actual) {
+ if (expected == -1) {
+ return false;
+ }
+ if (expected > actual) {
+ log.info("expecting {} version {} but my version is {}", label,
expected, actual);
+ return true;
+ }
+ log.info("I already have the expected version {} of {}", expected, label);
+ return false;
+ }
+
@Override
public Name getPermissionName(AuthorizationContext ctx) {
switch (ctx.getHttpMethod()) {
diff --git
a/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java
b/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java
index d46738ea347..80d46e7bac6 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java
@@ -30,6 +30,8 @@ import java.util.Map;
import org.apache.solr.api.JerseyResource;
import org.apache.solr.client.api.endpoint.ConfigApi;
import org.apache.solr.client.api.model.ConfigInfoResponse;
+import org.apache.solr.client.api.model.ConfigOverlayResponse;
+import org.apache.solr.client.api.model.ConfigZnodeVersionResponse;
import org.apache.solr.common.params.MapSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;
@@ -37,6 +39,7 @@ import org.apache.solr.common.util.StrUtils;
import org.apache.solr.common.util.Utils;
import org.apache.solr.core.PluginInfo;
import org.apache.solr.handler.RequestHandlerBase;
+import org.apache.solr.handler.SolrConfigHandler;
import org.apache.solr.jersey.NullKeyTolerantMap;
import org.apache.solr.jersey.PermissionName;
import org.apache.solr.request.SolrQueryRequest;
@@ -60,6 +63,32 @@ public class GetConfig extends JerseyResource implements
ConfigApi.Get {
return response;
}
+ @Override
+ @PermissionName(CONFIG_READ_PERM)
+ public ConfigOverlayResponse getOverlay() {
+ final var response =
instantiateJerseyResponse(ConfigOverlayResponse.class);
+ response.overlay =
+ Utils.convertToMap(
+ solrQueryRequest.getCore().getSolrConfig().getOverlay(), new
LinkedHashMap<>());
+ return response;
+ }
+
+ @Override
+ @PermissionName(CONFIG_READ_PERM)
+ public ConfigZnodeVersionResponse getZnodeVersion(
+ int expectedOverlayVersion, int expectedParamsVersion) {
+ final var response =
instantiateJerseyResponse(ConfigZnodeVersionResponse.class);
+ final var core = solrQueryRequest.getCore();
+ final var solrConfig = core.getSolrConfig();
+
+ response.znodeVersion = new ConfigZnodeVersionResponse.ZnodeVersions();
+ response.znodeVersion.overlay = solrConfig.getOverlay().getVersion();
+ response.znodeVersion.params =
solrConfig.getRequestParams().getZnodeVersion();
+
+ SolrConfigHandler.maybeRefreshStaleConfig(core, expectedOverlayVersion,
expectedParamsVersion);
+ return response;
+ }
+
@SuppressWarnings({"unchecked"})
private Map<String, Object> buildConfigMap(
SolrQueryRequest solrQueryRequest, boolean expandParams) {
diff --git
a/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfigAPI.java
b/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfigAPI.java
index 2a2db95683e..6a0567c987c 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfigAPI.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfigAPI.java
@@ -59,8 +59,6 @@ public class GetConfigAPI {
// Delete a path from this list when that section is migrated to Jersey
@EndPoint(
path = {
- "/config/overlay",
- "/config/znodeVersion",
"/config/luceneMatchVersion",
"/config/query",
"/config/requestHandler",
diff --git
a/solr/core/src/test/org/apache/solr/handler/admin/V2ConfigAPIMappingTest.java
b/solr/core/src/test/org/apache/solr/handler/admin/V2ConfigAPIMappingTest.java
index 0498b25dd5c..252946a5971 100644
---
a/solr/core/src/test/org/apache/solr/handler/admin/V2ConfigAPIMappingTest.java
+++
b/solr/core/src/test/org/apache/solr/handler/admin/V2ConfigAPIMappingTest.java
@@ -49,11 +49,9 @@ public class V2ConfigAPIMappingTest extends
V2ApiMappingTest<SolrConfigHandler>
// the API lookup works for a handful of the valid config "components".
@Test
public void testGetSingleComponentConfig() {
- assertAnnotatedApiExistsFor("GET", "/config/overlay");
assertAnnotatedApiExistsFor("GET", "/config/query");
assertAnnotatedApiExistsFor("GET", "/config/jmx");
assertAnnotatedApiExistsFor("GET", "/config/requestDispatcher");
- assertAnnotatedApiExistsFor("GET", "/config/znodeVersion");
assertAnnotatedApiExistsFor("GET", "/config/luceneMatchVersion");
assertAnnotatedApiExistsFor("GET", "/config/indexConfigdeletionPolicy");
assertAnnotatedApiExistsFor("GET", "/config/updateHandlerupdateLog");
diff --git
a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java
b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java
index 297da96353d..7ce43a5ff3d 100644
---
a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java
+++
b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java
@@ -40,7 +40,7 @@ public class GetConfigSolrCloudTest extends SolrCloudTestCase
{
}
@Test
- public void testGetConfigFromCore() throws Exception {
+ public void testGetConfigFromCollection() throws Exception {
var request = new ConfigApi.GetConfig(IndexType.COLLECTION,
COLLECTION_NAME);
var response = request.process(cluster.getSolrClient());
@@ -52,4 +52,28 @@ public class GetConfigSolrCloudTest extends
SolrCloudTestCase {
assertTrue(response.config.containsKey("query"));
assertTrue(response.config.containsKey("requestHandler"));
}
+
+ @Test
+ public void testGetOverlayFromCollection() throws Exception {
+ var request = new ConfigApi.GetOverlay(IndexType.COLLECTION,
COLLECTION_NAME);
+ var response = request.process(cluster.getSolrClient());
+
+ assertNotNull(response);
+ assertNull(response.error);
+ assertNotNull(response.overlay);
+ assertTrue(response.overlay.containsKey("znodeVersion"));
+ assertEquals(-1, response.overlay.get("znodeVersion"));
+ }
+
+ @Test
+ public void testGetZnodeVersionFromCollection() throws Exception {
+ var request = new ConfigApi.GetZnodeVersion(IndexType.COLLECTION,
COLLECTION_NAME);
+ var response = request.process(cluster.getSolrClient());
+
+ assertNotNull(response);
+ assertNull(response.error);
+ assertNotNull(response.znodeVersion);
+ assertTrue(response.znodeVersion.overlay >= -1);
+ assertTrue(response.znodeVersion.params >= -1);
+ }
}
diff --git
a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigTest.java
b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigTest.java
index c122e8d497a..a17d9258a18 100644
--- a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigTest.java
@@ -56,4 +56,28 @@ public class GetConfigTest extends SolrTestCase {
assertTrue(response.config.containsKey("searchComponent"));
assertTrue(response.config.containsKey("updateProcessor"));
}
+
+ @Test
+ public void testGetOverlayFromCore() throws Exception {
+ var request = new ConfigApi.GetOverlay(IndexType.CORE, CORE_NAME);
+ var response = request.process(solrTestRule.getSolrClient(CORE_NAME));
+
+ assertNotNull(response);
+ assertNull(response.error);
+ assertNotNull(response.overlay);
+ assertTrue(response.overlay.containsKey("znodeVersion"));
+ assertEquals(-1, response.overlay.get("znodeVersion"));
+ }
+
+ @Test
+ public void testGetZnodeVersionFromCore() throws Exception {
+ var request = new ConfigApi.GetZnodeVersion(IndexType.CORE, CORE_NAME);
+ var response = request.process(solrTestRule.getSolrClient(CORE_NAME));
+
+ assertNotNull(response);
+ assertNull(response.error);
+ assertNotNull(response.znodeVersion);
+ assertTrue(response.znodeVersion.overlay >= -1);
+ assertTrue(response.znodeVersion.params >= -1);
+ }
}
diff --git a/solr/solrj/src/resources/java-template/api.mustache
b/solr/solrj/src/resources/java-template/api.mustache
index 4aae4828561..b8c0dce8168 100644
--- a/solr/solrj/src/resources/java-template/api.mustache
+++ b/solr/solrj/src/resources/java-template/api.mustache
@@ -233,14 +233,14 @@ public class {{classname}} {
@Override
public SolrParams getParams() {
- final ModifiableSolrParams params = new ModifiableSolrParams();
+ final ModifiableSolrParams solrParams = new
ModifiableSolrParams();
{{#queryParams}}
if ({{paramName}} != null) {
- {{#isArray}}{{paramName}}.forEach(v ->
params.add("{{baseName}}",
v{{^items.isString}}.toString(){{/items.isString}}));{{/isArray}}
- {{^isArray}}params.add("{{baseName}}",
{{paramName}}{{^isString}}.toString(){{/isString}});{{/isArray}}
+ {{#isArray}}{{paramName}}.forEach(v ->
solrParams.add("{{baseName}}",
v{{^items.isString}}.toString(){{/items.isString}}));{{/isArray}}
+ {{^isArray}}solrParams.add("{{baseName}}",
{{paramName}}{{^isString}}.toString(){{/isString}});{{/isArray}}
}
{{/queryParams}}
- return params;
+ return solrParams;
}
@Override